org.postgresql.benchmark.statement.ProcessResultSet Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of pgjdbc-benchmark Show documentation
Show all versions of pgjdbc-benchmark Show documentation
PostgreSQL JDBC Driver - benchmarks
/*
* Copyright (c) 2003, PostgreSQL Global Development Group
* See the LICENSE file in the project root for more information.
*/
package org.postgresql.benchmark.statement;
import org.postgresql.util.ConnectionUtil;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Level;
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.TearDown;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.infra.Blackhole;
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.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.Properties;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
/**
* Tests the performance of preparing, executing and performing a fetch out of a simple "SELECT ?,
* ?, ... ?" statement.
*/
@Fork(value = 1, jvmArgsPrepend = "-Xmx128m")
@Measurement(iterations = 10, time = 1, timeUnit = TimeUnit.SECONDS)
@Warmup(iterations = 10, time = 1, timeUnit = TimeUnit.SECONDS)
@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public class ProcessResultSet {
public enum FieldType {
INT,
BIGINT,
BIGDECIMAL,
STRING,
TIMESTAMP,
TIMESTAMPTZ,
BOOL
}
public enum ColumnIndexType {
INDEX,
NAME
}
public enum GetterType {
BEST,
OBJECT
}
@Param({"1", "50", "100"})
private int nrows;
@Param({"5"})
private int ncols;
@Param
private FieldType type;
@Param({"false"})
public boolean unique;
@Param({"BEST"})
public GetterType getter;
@Param({"NAME"})
public ColumnIndexType columnIndexType;
// Reuse == false is in line with what most applications do. They never reuse PreparedStatement objects
@Param({"false"})
public boolean reuseStatement;
private Connection connection;
private PreparedStatement ps;
private String sql;
private int cntr;
private String[] columnNames;
@Setup(Level.Trial)
public void setUp() throws SQLException {
if (reuseStatement && unique) {
System.out.println("It does not make sense to test reuseStatement && unique combination. Terminating to save time");
System.exit(-1);
}
if (type == FieldType.TIMESTAMP) {
System.out.println(
"TimeZone.getDefault().getDisplayName() = " + TimeZone.getDefault().getDisplayName());
}
Properties props = ConnectionUtil.getProperties();
connection = DriverManager.getConnection(ConnectionUtil.getURL(), props);
StringBuilder sb = new StringBuilder();
sb.append("SELECT ");
columnNames = new String[ncols];
for (int i = 0; i < ncols; i++) {
if (i > 0) {
sb.append(", ");
}
if (type == FieldType.INT) {
sb.append("t.x");
}
if (type == FieldType.BIGINT) {
sb.append("1234567890123456789");
}
if (type == FieldType.BIGDECIMAL) {
sb.append("12345678901234567890123456789");
} else if (type == FieldType.STRING) {
sb.append("'test string'");
} else if (type == FieldType.TIMESTAMP) {
sb.append("localtimestamp");
} else if (type == FieldType.TIMESTAMPTZ) {
sb.append("current_timestamp");
} else if (type == FieldType.BOOL) {
sb.append("TRUE");
}
String columnName = "c" + String.valueOf(System.currentTimeMillis()) + String.valueOf(i);
columnNames[i] = columnName;
sb.append(' ').append(columnName);
}
sb.append(" from generate_series(1, ?) as t(x)");
sql = sb.toString();
if (reuseStatement) {
this.ps = connection.prepareStatement(sql);
}
}
@TearDown(Level.Trial)
public void tearDown() throws SQLException {
connection.close();
}
@Benchmark
public Statement bindExecuteFetch(Blackhole b) throws SQLException {
String sql = this.sql;
if (unique) {
sql += " -- " + cntr++;
}
PreparedStatement ps = reuseStatement ? this.ps : connection.prepareStatement(sql);
ps.setInt(1, nrows);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
for (int i = 1; i <= ncols; i++) {
if (columnIndexType == ColumnIndexType.INDEX) {
getByIndex(b, rs, i);
} else {
getByName(b, rs, columnNames[i - 1]);
}
}
}
rs.close();
if (!reuseStatement) {
ps.close();
}
return ps;
}
private void getByIndex(Blackhole b, ResultSet rs, int i) throws SQLException {
if (getter == GetterType.OBJECT) {
b.consume(rs.getObject(i));
} else if (type == FieldType.INT) {
b.consume(rs.getInt(i));
} else if (type == FieldType.BIGINT) {
b.consume(rs.getBigDecimal(i));
} else if (type == FieldType.BIGDECIMAL) {
b.consume(rs.getBigDecimal(i));
} else if (type == FieldType.STRING) {
b.consume(rs.getString(i));
} else if (type == FieldType.TIMESTAMP) {
b.consume(rs.getTimestamp(i));
} else if (type == FieldType.TIMESTAMPTZ) {
b.consume(rs.getTimestamp(i));
} else if (type == FieldType.BOOL) {
b.consume(rs.getBoolean(i));
}
}
private void getByName(Blackhole b, ResultSet rs, String i) throws SQLException {
if (getter == GetterType.OBJECT) {
b.consume(rs.getObject(i));
} else if (type == FieldType.INT) {
b.consume(rs.getInt(i));
} else if (type == FieldType.BIGINT) {
b.consume(rs.getBigDecimal(i));
} else if (type == FieldType.BIGDECIMAL) {
b.consume(rs.getBigDecimal(i));
} else if (type == FieldType.STRING) {
b.consume(rs.getString(i));
} else if (type == FieldType.TIMESTAMP) {
b.consume(rs.getTimestamp(i));
} else if (type == FieldType.TIMESTAMPTZ) {
b.consume(rs.getTimestamp(i));
} else if (type == FieldType.BOOL) {
b.consume(rs.getBoolean(i));
}
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(ProcessResultSet.class.getSimpleName())
//.addProfiler(GCProfiler.class)
.detectJvmArgs()
.build();
new Runner(opt).run();
}
}