You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by vl...@apache.org on 2016/01/09 11:36:48 UTC
calcite git commit: Add benchmark of Parser.create(sql).parseQuery()
Repository: calcite
Updated Branches:
refs/heads/master b94a00e33 -> 08647e71e
Add benchmark of Parser.create(sql).parseQuery()
Closes #176
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/08647e71
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/08647e71
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/08647e71
Branch: refs/heads/master
Commit: 08647e71ef31ed13beca904273f6cf3bc6e41199
Parents: b94a00e
Author: Vladimir Sitnikov <si...@gmail.com>
Authored: Sat Jan 9 13:36:33 2016 +0300
Committer: Vladimir Sitnikov <si...@gmail.com>
Committed: Sat Jan 9 13:36:33 2016 +0300
----------------------------------------------------------------------
1/Vagrantfile | 56 ++++
.../apache/calcite/sql/parser/SqlParser.java | 25 +-
pom.xml | 4 +-
ubenchmark/pom.xml | 5 +-
.../java/org/apache/calcite/StatementTest.java | 264 -------------------
.../benchmarks/FlightRecorderProfiler.java | 87 ++++++
.../calcite/benchmarks/ParserBenchmark.java | 121 +++++++++
.../calcite/benchmarks/PreconditionTest.java | 56 ++++
.../calcite/benchmarks/StatementTest.java | 264 +++++++++++++++++++
.../apache/calcite/benchmarks/package-info.java | 26 ++
10 files changed, 631 insertions(+), 277 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite/blob/08647e71/1/Vagrantfile
----------------------------------------------------------------------
diff --git a/1/Vagrantfile b/1/Vagrantfile
new file mode 100644
index 0000000..36baec2
--- /dev/null
+++ b/1/Vagrantfile
@@ -0,0 +1,56 @@
+# 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.
+
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+
+Vagrant.configure(2) do |config|
+ config.vm.box = "puppetlabs/ubuntu-14.04-64-puppet"
+ config.vm.box_url = "https://vagrantcloud.com/puppetlabs/boxes/ubuntu-14.04-32-puppet/versions/1/providers/virtualbox.box"
+
+ config.vm.define :ubuntucalcite do |ubuntucalcite|
+ ubuntucalcite.vm.network :forwarded_port, guest: 27017, host: 27017 # mongodb
+ ubuntucalcite.vm.network :forwarded_port, guest: 5432, host: 5432 # postgresql
+ ubuntucalcite.vm.network :forwarded_port, guest: 3306, host: 3306 # mysql
+ ubuntucalcite.vm.network :forwarded_port, guest: 8089, host: 8089 # splunk
+
+ ubuntucalcite.vm.hostname = "ubuntucalcite2"
+
+ ubuntucalcite.vm.provider :virtualbox do |v|
+ # This allows symlinks to be created within the /vagrant root directory,
+ # which is something librarian-puppet needs to be able to do. This might
+ # be enabled by default depending on what version of VirtualBox is used.
+ v.customize ["setextradata", :id, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/v-root", "1"]
+
+ v.customize ['modifyvm', :id, '--name', 'ubuntu1404-calcite']
+ v.customize ['modifyvm', :id, '--cpus', '1']
+ v.customize ['modifyvm', :id, '--memory', 512]
+ v.customize ['modifyvm', :id, '--ioapic', 'off']
+ v.customize ['modifyvm', :id, '--natdnshostresolver1', 'on']
+ v.customize ['modifyvm', :id, '--nictype1', 'virtio']
+ v.customize ['modifyvm', :id, '--nictype2', 'virtio']
+ end
+
+ ubuntucalcite.vm.provision :file, source: "Puppetfile", destination: "/home/vagrant/puppet/Puppetfile"
+ ubuntucalcite.vm.provision :shell, inline: "if [[ ! -f /apt-get-run ]]; then apt-get update && sudo touch /apt-get-run; fi"
+ ubuntucalcite.vm.provision :shell, inline: "apt-get install -y git-core ruby-dev unzip"
+ ubuntucalcite.vm.provision :shell, inline: "gem install --verbose librarian-puppet"
+ ubuntucalcite.vm.provision :shell, inline: "cd puppet && librarian-puppet install --verbose"
+ ubuntucalcite.vm.provision :shell, inline: "cd puppet && puppet apply -vv --modulepath=modules /vagrant/default.pp"
+
+ # Populate MongoDB
+ ubuntucalcite.vm.provision :shell, path: "init_mongodb.sh"
+ end
+end
http://git-wip-us.apache.org/repos/asf/calcite/blob/08647e71/core/src/main/java/org/apache/calcite/sql/parser/SqlParser.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/parser/SqlParser.java b/core/src/main/java/org/apache/calcite/sql/parser/SqlParser.java
index 4c14395..e1bda73 100644
--- a/core/src/main/java/org/apache/calcite/sql/parser/SqlParser.java
+++ b/core/src/main/java/org/apache/calcite/sql/parser/SqlParser.java
@@ -133,22 +133,27 @@ public class SqlParser {
}
/**
+ * Parses a <code>SELECT</code> statement and reuses parser.
+ *
+ * @param sql sql to parse
+ * @return A {@link org.apache.calcite.sql.SqlSelect} for a regular <code>
+ * SELECT</code> statement; a {@link org.apache.calcite.sql.SqlBinaryOperator}
+ * for a <code>UNION</code>, <code>INTERSECT</code>, or <code>EXCEPT</code>.
+ * @throws SqlParseException if there is a parse error
+ */
+ public SqlNode parseQuery(String sql) throws SqlParseException {
+ parser.ReInit(new StringReader(sql));
+ return parseQuery();
+ }
+
+ /**
* Parses an SQL statement.
*
* @return top-level SqlNode representing stmt
* @throws SqlParseException if there is a parse error
*/
public SqlNode parseStmt() throws SqlParseException {
- try {
- return parser.parseSqlStmtEof();
- } catch (Throwable ex) {
- if ((ex instanceof CalciteContextException)
- && (originalInput != null)) {
- ((CalciteContextException) ex).setOriginalStatement(
- originalInput);
- }
- throw parser.normalizeException(ex);
- }
+ return parseQuery();
}
/**
http://git-wip-us.apache.org/repos/asf/calcite/blob/08647e71/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 9ac5596..3253f25 100644
--- a/pom.xml
+++ b/pom.xml
@@ -295,12 +295,12 @@ limitations under the License.
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
- <version>0.7.1</version>
+ <version>1.11.2</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
- <version>0.7.1</version>
+ <version>1.11.2</version>
</dependency>
<dependency>
<groupId>sqlline</groupId>
http://git-wip-us.apache.org/repos/asf/calcite/blob/08647e71/ubenchmark/pom.xml
----------------------------------------------------------------------
diff --git a/ubenchmark/pom.xml b/ubenchmark/pom.xml
index 1f1752c..e50d4dd 100644
--- a/ubenchmark/pom.xml
+++ b/ubenchmark/pom.xml
@@ -55,6 +55,10 @@ limitations under the License.
<artifactId>jmh-generator-annprocess</artifactId>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
</dependencies>
<build>
@@ -64,7 +68,6 @@ limitations under the License.
<configuration>
<source>1.6</source>
<target>1.6</target>
- <compilerArgument>-proc:none</compilerArgument>
</configuration>
</plugin>
<plugin>
http://git-wip-us.apache.org/repos/asf/calcite/blob/08647e71/ubenchmark/src/main/java/org/apache/calcite/StatementTest.java
----------------------------------------------------------------------
diff --git a/ubenchmark/src/main/java/org/apache/calcite/StatementTest.java b/ubenchmark/src/main/java/org/apache/calcite/StatementTest.java
deleted file mode 100644
index b8a7d2f..0000000
--- a/ubenchmark/src/main/java/org/apache/calcite/StatementTest.java
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * 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;
-
-import org.apache.calcite.adapter.java.ReflectiveSchema;
-import org.apache.calcite.jdbc.CalciteConnection;
-import org.apache.calcite.schema.SchemaPlus;
-
-import org.openjdk.jmh.annotations.BenchmarkMode;
-import org.openjdk.jmh.annotations.GenerateMicroBenchmark;
-import org.openjdk.jmh.annotations.Level;
-import org.openjdk.jmh.annotations.Mode;
-import org.openjdk.jmh.annotations.Scope;
-import org.openjdk.jmh.annotations.Setup;
-import org.openjdk.jmh.annotations.State;
-
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Properties;
-import java.util.Random;
-
-/**
- * Compares {@link java.sql.Statement} vs {@link java.sql.PreparedStatement}.
- *
- * <p>This package contains micro-benchmarks to test calcite performance.
- *
- * <p>To run this and other benchmarks:
- *
- * <blockquote>
- * <code>mvn package &&
- * java -jar ./target/ubenchmarks.jar -wi 5 -i 5 -f 1</code>
- * </blockquote>
- *
- * <p>To run with profiling:
- *
- * <blockquote>
- * <code>java -Djmh.stack.lines=10 -jar ./target/ubenchmarks.jar
- * -prof hs_comp,hs_gc,stack -f 1 -wi 5</code>
- * </blockquote>
- */
-public class StatementTest {
-
- /**
- * Connection to be used during tests.
- */
- @State(Scope.Thread)
- @BenchmarkMode(Mode.AverageTime)
- public static class HrConnection {
- Connection con;
- int id;
- HrSchema hr = new HrSchema();
- Random rnd = new Random();
- {
- try {
- Class.forName("org.apache.calcite.jdbc.Driver");
- } catch (ClassNotFoundException e) {
- throw new IllegalStateException(e);
- }
- Connection connection;
-
- try {
- Properties info = new Properties();
- info.put("lex", "JAVA");
- info.put("quoting", "DOUBLE_QUOTE");
- connection = DriverManager.getConnection("jdbc:calcite:", info);
- } catch (SQLException e) {
- throw new IllegalStateException(e);
- }
- CalciteConnection calciteConnection;
- try {
- calciteConnection = connection.unwrap(CalciteConnection.class);
- } catch (SQLException e) {
- throw new IllegalStateException(e);
- }
- final SchemaPlus rootSchema = calciteConnection.getRootSchema();
- rootSchema.add("hr", new ReflectiveSchema(new HrSchema()));
- try {
- calciteConnection.setSchema("hr");
- } catch (SQLException e) {
- throw new IllegalStateException(e);
- }
- con = connection;
- }
-
- @Setup(Level.Iteration)
- public void pickEmployee() {
- id = hr.emps[rnd.nextInt(4)].empid;
- }
- }
-
- /**
- * Tests performance of reused execution of prepared statement.
- */
- public static class HrPreparedStatement extends HrConnection {
- PreparedStatement ps;
- {
- try {
- ps = con.prepareStatement("select name from emps where empid = ?");
- } catch (SQLException e) {
- throw new IllegalStateException(e);
- }
- }
- }
-
- @GenerateMicroBenchmark
- public String prepareBindExecute(HrConnection state) throws SQLException {
- Connection con = state.con;
- Statement st = null;
- ResultSet rs = null;
- String ename = null;
- try {
- final PreparedStatement ps =
- con.prepareStatement("select name from emps where empid = ?");
- st = ps;
- ps.setInt(1, state.id);
- rs = ps.executeQuery();
- rs.next();
- ename = rs.getString(1);
- } finally {
- close(rs, st);
- }
- return ename;
- }
-
- @GenerateMicroBenchmark
- public String bindExecute(HrPreparedStatement state)
- throws SQLException {
- PreparedStatement st = state.ps;
- ResultSet rs = null;
- String ename = null;
- try {
- st.setInt(1, state.id);
- rs = st.executeQuery();
- rs.next();
- ename = rs.getString(1);
- } finally {
- close(rs, null); // Statement is not closed
- }
- return ename;
- }
-
- @GenerateMicroBenchmark
- public String executeQuery(HrConnection state) throws SQLException {
- Connection con = state.con;
- Statement st = null;
- ResultSet rs = null;
- String ename = null;
- try {
- st = con.createStatement();
- rs = st.executeQuery("select name from emps where empid = " + state.id);
- rs.next();
- ename = rs.getString(1);
- } finally {
- close(rs, st);
- }
- return ename;
- }
-
- @GenerateMicroBenchmark
- public String forEach(HrConnection state) throws SQLException {
- final Employee[] emps = state.hr.emps;
- for (Employee emp : emps) {
- if (emp.empid == state.id) {
- return emp.name;
- }
- }
- return null;
- }
-
- private static void close(ResultSet rs, Statement st) {
- if (rs != null) {
- try { rs.close(); } catch (SQLException e) { /**/ }
- }
- if (st != null) {
- try { st.close(); } catch (SQLException e) { /**/ }
- }
- }
-
- /** Pojo schema containing "emps" and "depts" tables. */
- public static class HrSchema {
- @Override public String toString() {
- return "HrSchema";
- }
-
- public final Employee[] emps = {
- new Employee(100, 10, "Bill", 10000, 1000),
- new Employee(200, 20, "Eric", 8000, 500),
- new Employee(150, 10, "Sebastian", 7000, null),
- new Employee(110, 10, "Theodore", 11500, 250),
- };
- public final Department[] depts = {
- new Department(10, "Sales", Arrays.asList(emps[0], emps[2])),
- new Department(30, "Marketing", Collections.<Employee>emptyList()),
- new Department(40, "HR", Collections.singletonList(emps[1])),
- };
- }
-
- /** Employee record. */
- public static class Employee {
- public final int empid;
- public final int deptno;
- public final String name;
- public final float salary;
- public final Integer commission;
-
- public Employee(int empid, int deptno, String name, float salary,
- Integer commission) {
- this.empid = empid;
- this.deptno = deptno;
- this.name = name;
- this.salary = salary;
- this.commission = commission;
- }
-
- public String toString() {
- return "Employee [empid: " + empid + ", deptno: " + deptno
- + ", name: " + name + "]";
- }
- }
-
- /** Department record. */
- public static class Department {
- public final int deptno;
- public final String name;
- public final List<Employee> employees;
-
- public Department(
- int deptno, String name, List<Employee> employees) {
- this.deptno = deptno;
- this.name = name;
- this.employees = employees;
- }
-
-
- public String toString() {
- return "Department [deptno: " + deptno + ", name: " + name
- + ", employees: " + employees + "]";
- }
- }
-
-}
-
-// End StatementTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/08647e71/ubenchmark/src/main/java/org/apache/calcite/benchmarks/FlightRecorderProfiler.java
----------------------------------------------------------------------
diff --git a/ubenchmark/src/main/java/org/apache/calcite/benchmarks/FlightRecorderProfiler.java b/ubenchmark/src/main/java/org/apache/calcite/benchmarks/FlightRecorderProfiler.java
new file mode 100644
index 0000000..451c004
--- /dev/null
+++ b/ubenchmark/src/main/java/org/apache/calcite/benchmarks/FlightRecorderProfiler.java
@@ -0,0 +1,87 @@
+/*
+ * 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.openjdk.jmh.infra.BenchmarkParams;
+import org.openjdk.jmh.infra.IterationParams;
+import org.openjdk.jmh.profile.ExternalProfiler;
+import org.openjdk.jmh.results.BenchmarkResult;
+import org.openjdk.jmh.results.Result;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Captures Flight Recorder log.
+ * Note: Flight Recorder is available in OracleJDK only.
+ * Usage of Flight Recorder in production requires a LICENSE FEE, however Flight Recorder is free
+ * for use in test systems.
+ * It is assumed you would not use Calcite benchmarks for running a production system, thus it is
+ * believed to be safe.
+ */
+public class FlightRecorderProfiler implements ExternalProfiler {
+ @Override public Collection<String> addJVMInvokeOptions(BenchmarkParams params) {
+ return Collections.emptyList();
+ }
+
+ @Override public Collection<String> addJVMOptions(BenchmarkParams params) {
+ StringBuilder sb = new StringBuilder();
+ for (String param : params.getParamsKeys()) {
+ if (sb.length() != 0) {
+ sb.append('-');
+ }
+ sb.append(param).append('-').append(params.getParam(param));
+ }
+
+ long duration =
+ getDurationSeconds(params.getWarmup()) + getDurationSeconds(params.getMeasurement());
+ return Arrays.asList(
+ "-XX:+UnlockCommercialFeatures", "-XX:+FlightRecorder",
+ "-XX:StartFlightRecording=settings=profile,duration=" + duration + "s,filename="
+ + params.getBenchmark() + "_" + sb + ".jfr");
+ }
+
+ private long getDurationSeconds(IterationParams warmup) {
+ return warmup.getTime().convertTo(TimeUnit.SECONDS) * warmup.getCount();
+ }
+
+ @Override public void beforeTrial(BenchmarkParams benchmarkParams) {
+
+ }
+
+ @Override public Collection<? extends Result> afterTrial(BenchmarkResult br, long pid,
+ File stdOut, File stdErr) {
+ return Collections.emptyList();
+ }
+
+ @Override public boolean allowPrintOut() {
+ return true;
+ }
+
+ @Override public boolean allowPrintErr() {
+ return true;
+ }
+
+ @Override public String getDescription() {
+ return "Collects Java Flight Recorder profile";
+ }
+}
+
+// End FlightRecorderProfiler.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/08647e71/ubenchmark/src/main/java/org/apache/calcite/benchmarks/ParserBenchmark.java
----------------------------------------------------------------------
diff --git a/ubenchmark/src/main/java/org/apache/calcite/benchmarks/ParserBenchmark.java b/ubenchmark/src/main/java/org/apache/calcite/benchmarks/ParserBenchmark.java
new file mode 100644
index 0000000..90e4e8a
--- /dev/null
+++ b/ubenchmark/src/main/java/org/apache/calcite/benchmarks/ParserBenchmark.java
@@ -0,0 +1,121 @@
+/*
+ * 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() throws SqlParseException {
+ 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;
+ }
+ }
+ 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();
+ }
+
+}
+
+// End ParserBenchmark.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/08647e71/ubenchmark/src/main/java/org/apache/calcite/benchmarks/PreconditionTest.java
----------------------------------------------------------------------
diff --git a/ubenchmark/src/main/java/org/apache/calcite/benchmarks/PreconditionTest.java b/ubenchmark/src/main/java/org/apache/calcite/benchmarks/PreconditionTest.java
new file mode 100644
index 0000000..c150a49
--- /dev/null
+++ b/ubenchmark/src/main/java/org/apache/calcite/benchmarks/PreconditionTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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 com.google.common.base.Preconditions;
+
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+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;
+
+/**
+ * Checks if silent precondition has noticeable overhead
+ */
+@BenchmarkMode(Mode.AverageTime)
+@State(Scope.Benchmark)
+public class PreconditionTest {
+ boolean fire = false;
+ String param = "world";
+
+ public void testPrecondition() {
+ Preconditions.checkState(fire, "Hello %s", param);
+ }
+
+ public static void main(String[] args) throws RunnerException {
+ Options opt = new OptionsBuilder()
+ .include(PreconditionTest.class.getSimpleName())
+ .addProfiler(GCProfiler.class)
+ .detectJvmArgs()
+ .build();
+
+ new Runner(opt).run();
+ }
+
+}
+
+// End PreconditionTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/08647e71/ubenchmark/src/main/java/org/apache/calcite/benchmarks/StatementTest.java
----------------------------------------------------------------------
diff --git a/ubenchmark/src/main/java/org/apache/calcite/benchmarks/StatementTest.java b/ubenchmark/src/main/java/org/apache/calcite/benchmarks/StatementTest.java
new file mode 100644
index 0000000..d716fdf
--- /dev/null
+++ b/ubenchmark/src/main/java/org/apache/calcite/benchmarks/StatementTest.java
@@ -0,0 +1,264 @@
+/*
+ * 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.adapter.java.ReflectiveSchema;
+import org.apache.calcite.jdbc.CalciteConnection;
+import org.apache.calcite.schema.SchemaPlus;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+import java.util.Random;
+
+/**
+ * Compares {@link java.sql.Statement} vs {@link java.sql.PreparedStatement}.
+ *
+ * <p>This package contains micro-benchmarks to test calcite performance.
+ *
+ * <p>To run this and other benchmarks:
+ *
+ * <blockquote>
+ * <code>mvn package &&
+ * java -jar ./target/ubenchmarks.jar -wi 5 -i 5 -f 1</code>
+ * </blockquote>
+ *
+ * <p>To run with profiling:
+ *
+ * <blockquote>
+ * <code>java -Djmh.stack.lines=10 -jar ./target/ubenchmarks.jar
+ * -prof hs_comp,hs_gc,stack -f 1 -wi 5</code>
+ * </blockquote>
+ */
+public class StatementTest {
+
+ /**
+ * Connection to be used during tests.
+ */
+ @State(Scope.Thread)
+ @BenchmarkMode(Mode.AverageTime)
+ public static class HrConnection {
+ Connection con;
+ int id;
+ HrSchema hr = new HrSchema();
+ Random rnd = new Random();
+ {
+ try {
+ Class.forName("org.apache.calcite.jdbc.Driver");
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException(e);
+ }
+ Connection connection;
+
+ try {
+ Properties info = new Properties();
+ info.put("lex", "JAVA");
+ info.put("quoting", "DOUBLE_QUOTE");
+ connection = DriverManager.getConnection("jdbc:calcite:", info);
+ } catch (SQLException e) {
+ throw new IllegalStateException(e);
+ }
+ CalciteConnection calciteConnection;
+ try {
+ calciteConnection = connection.unwrap(CalciteConnection.class);
+ } catch (SQLException e) {
+ throw new IllegalStateException(e);
+ }
+ final SchemaPlus rootSchema = calciteConnection.getRootSchema();
+ rootSchema.add("hr", new ReflectiveSchema(new HrSchema()));
+ try {
+ calciteConnection.setSchema("hr");
+ } catch (SQLException e) {
+ throw new IllegalStateException(e);
+ }
+ con = connection;
+ }
+
+ @Setup(Level.Iteration)
+ public void pickEmployee() {
+ id = hr.emps[rnd.nextInt(4)].empid;
+ }
+ }
+
+ /**
+ * Tests performance of reused execution of prepared statement.
+ */
+ public static class HrPreparedStatement extends HrConnection {
+ PreparedStatement ps;
+ {
+ try {
+ ps = con.prepareStatement("select name from emps where empid = ?");
+ } catch (SQLException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+
+ @Benchmark
+ public String prepareBindExecute(HrConnection state) throws SQLException {
+ Connection con = state.con;
+ Statement st = null;
+ ResultSet rs = null;
+ String ename = null;
+ try {
+ final PreparedStatement ps =
+ con.prepareStatement("select name from emps where empid = ?");
+ st = ps;
+ ps.setInt(1, state.id);
+ rs = ps.executeQuery();
+ rs.next();
+ ename = rs.getString(1);
+ } finally {
+ close(rs, st);
+ }
+ return ename;
+ }
+
+ @Benchmark
+ public String bindExecute(HrPreparedStatement state)
+ throws SQLException {
+ PreparedStatement st = state.ps;
+ ResultSet rs = null;
+ String ename = null;
+ try {
+ st.setInt(1, state.id);
+ rs = st.executeQuery();
+ rs.next();
+ ename = rs.getString(1);
+ } finally {
+ close(rs, null); // Statement is not closed
+ }
+ return ename;
+ }
+
+ @Benchmark
+ public String executeQuery(HrConnection state) throws SQLException {
+ Connection con = state.con;
+ Statement st = null;
+ ResultSet rs = null;
+ String ename = null;
+ try {
+ st = con.createStatement();
+ rs = st.executeQuery("select name from emps where empid = " + state.id);
+ rs.next();
+ ename = rs.getString(1);
+ } finally {
+ close(rs, st);
+ }
+ return ename;
+ }
+
+ @Benchmark
+ public String forEach(HrConnection state) throws SQLException {
+ final Employee[] emps = state.hr.emps;
+ for (Employee emp : emps) {
+ if (emp.empid == state.id) {
+ return emp.name;
+ }
+ }
+ return null;
+ }
+
+ private static void close(ResultSet rs, Statement st) {
+ if (rs != null) {
+ try { rs.close(); } catch (SQLException e) { /**/ }
+ }
+ if (st != null) {
+ try { st.close(); } catch (SQLException e) { /**/ }
+ }
+ }
+
+ /** Pojo schema containing "emps" and "depts" tables. */
+ public static class HrSchema {
+ @Override public String toString() {
+ return "HrSchema";
+ }
+
+ public final Employee[] emps = {
+ new Employee(100, 10, "Bill", 10000, 1000),
+ new Employee(200, 20, "Eric", 8000, 500),
+ new Employee(150, 10, "Sebastian", 7000, null),
+ new Employee(110, 10, "Theodore", 11500, 250),
+ };
+ public final Department[] depts = {
+ new Department(10, "Sales", Arrays.asList(emps[0], emps[2])),
+ new Department(30, "Marketing", Collections.<Employee>emptyList()),
+ new Department(40, "HR", Collections.singletonList(emps[1])),
+ };
+ }
+
+ /** Employee record. */
+ public static class Employee {
+ public final int empid;
+ public final int deptno;
+ public final String name;
+ public final float salary;
+ public final Integer commission;
+
+ public Employee(int empid, int deptno, String name, float salary,
+ Integer commission) {
+ this.empid = empid;
+ this.deptno = deptno;
+ this.name = name;
+ this.salary = salary;
+ this.commission = commission;
+ }
+
+ public String toString() {
+ return "Employee [empid: " + empid + ", deptno: " + deptno
+ + ", name: " + name + "]";
+ }
+ }
+
+ /** Department record. */
+ public static class Department {
+ public final int deptno;
+ public final String name;
+ public final List<Employee> employees;
+
+ public Department(
+ int deptno, String name, List<Employee> employees) {
+ this.deptno = deptno;
+ this.name = name;
+ this.employees = employees;
+ }
+
+
+ public String toString() {
+ return "Department [deptno: " + deptno + ", name: " + name
+ + ", employees: " + employees + "]";
+ }
+ }
+
+}
+
+// End StatementTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/08647e71/ubenchmark/src/main/java/org/apache/calcite/benchmarks/package-info.java
----------------------------------------------------------------------
diff --git a/ubenchmark/src/main/java/org/apache/calcite/benchmarks/package-info.java b/ubenchmark/src/main/java/org/apache/calcite/benchmarks/package-info.java
new file mode 100644
index 0000000..3146cae
--- /dev/null
+++ b/ubenchmark/src/main/java/org/apache/calcite/benchmarks/package-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+/**
+ * JMH benchmarks for Calcite
+ */
+@PackageMarker
+package org.apache.calcite.benchmarks;
+
+import org.apache.calcite.avatica.util.PackageMarker;
+
+// End package-info.java