content: /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to you under the Apache License, Version 2.0
   * (the "License"); you may not use this file except in compliance with
   * the License.  You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.calcite.benchmarks;
  
  import org.apache.calcite.sql.SqlNode;
  import org.apache.calcite.sql.parser.SqlParseException;
  import org.apache.calcite.sql.parser.SqlParser;
  
  import org.openjdk.jmh.annotations.Benchmark;
  import org.openjdk.jmh.annotations.BenchmarkMode;
  import org.openjdk.jmh.annotations.Fork;
  import org.openjdk.jmh.annotations.Measurement;
  import org.openjdk.jmh.annotations.Mode;
  import org.openjdk.jmh.annotations.OutputTimeUnit;
  import org.openjdk.jmh.annotations.Param;
  import org.openjdk.jmh.annotations.Scope;
  import org.openjdk.jmh.annotations.Setup;
  import org.openjdk.jmh.annotations.State;
  import org.openjdk.jmh.annotations.Threads;
  import org.openjdk.jmh.annotations.Warmup;
  import org.openjdk.jmh.profile.GCProfiler;
  import org.openjdk.jmh.runner.Runner;
  import org.openjdk.jmh.runner.RunnerException;
  import org.openjdk.jmh.runner.options.Options;
  import org.openjdk.jmh.runner.options.OptionsBuilder;
  
  import java.util.Random;
  import java.util.concurrent.TimeUnit;
  
  /**
   * Benchmarks JavaCC-generated SQL parser.
   */
  @Fork(value = 1, jvmArgsPrepend = "-Xmx128m")
  @Measurement(iterations = 7, time = 1, timeUnit = TimeUnit.SECONDS)
  @Warmup(iterations = 7, time = 1, timeUnit = TimeUnit.SECONDS)
  @State(Scope.Thread)
  @Threads(1)
  @BenchmarkMode(Mode.AverageTime)
  @OutputTimeUnit(TimeUnit.MICROSECONDS)
  public class ParserBenchmark {
  
    @Param({ "1000" })
    int length;
  
    @Param({ "true" })
    boolean comments;
  
    String sql;
    SqlParser parser;
  
    @Setup
    public void setup() {
      StringBuilder sb = new StringBuilder((int) (length * 1.2));
      sb.append("select 1");
      Random rnd = new Random();
      rnd.setSeed(424242);
      for (; sb.length() < length;) {
        for (int i = 0; i < 7 && sb.length() < length; i++) {
          sb.append(", ");
          switch (rnd.nextInt(3)) {
          case 0:
            sb.append("?");
            break;
          case 1:
            sb.append(rnd.nextInt());
            break;
          case 2:
            sb.append('\'').append(rnd.nextLong()).append(rnd.nextLong())
                .append('\'');
            break;
          default:
            break;
          }
        }
        if (comments && sb.length() < length) {
          sb.append("// sb.append('\\'').append(rnd.nextLong()).append(rnd.nextLong()).append(rnd"
              + ".nextLong())");
        }
        sb.append('\n');
      }
      sb.append(" from dual");
      parser = SqlParser.create("values(1)");
      sql = sb.toString();
    }
  
    @Benchmark
    public SqlNode parseCached() throws SqlParseException {
      return parser.parseQuery(sql);
    }
  
    @Benchmark
    public SqlNode parseNonCached() throws SqlParseException {
      return SqlParser.create(sql).parseQuery();
    }
  
    public static void main(String[] args) throws RunnerException {
      Options opt = new OptionsBuilder()
          .include(ParserBenchmark.class.getSimpleName())
          .addProfiler(GCProfiler.class)
          .addProfiler(FlightRecorderProfiler.class)
          .detectJvmArgs()
          .build();
  
      new Runner(opt).run();
    }
  
  }
  