Skip to content

Instantly share code, notes, and snippets.

@davidecavestro
Last active July 25, 2019 04:40
Show Gist options
  • Save davidecavestro/5910882 to your computer and use it in GitHub Desktop.
Save davidecavestro/5910882 to your computer and use it in GitHub Desktop.
H2 serialization performance test
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
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.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.InputMismatchException;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import org.h2.api.JavaObjectSerializer;
import org.jboss.serial.io.JBossObjectInputStream;
import org.jboss.serial.io.JBossObjectOutputStream;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
public class Main {
private static final int STEP = 10;
private static final int SAMPLES_COUNT = 10;
private static final int MAX_ROWS = 10000;
private static final int CALENDAR_COUNT = 50;
private String url;
public static void main (final String[] args) throws Exception {
final File dbDir = new File (System.getProperty ("java.io.tmpdir"), "h2perftest");
// executeUserDriven (dbDIr);
acquireStats (dbDir);
}
private static void acquireStats (final File dbDir) throws Exception {
final int samplesCount = SAMPLES_COUNT;
final Map<String, List<Long>> stats = new LinkedHashMap<String, List<Long>> ();
final int maxRows = MAX_ROWS;
for (int rowCount = 1; rowCount <= maxRows; rowCount = rowCount * STEP) {
List<Long> rowStats = new LinkedList<Long> ();
stats.put (Integer.toString (rowCount), rowStats);
for (int sampleNum = 0; sampleNum < samplesCount; sampleNum++) {
Main main = new Main ();
long time = main.work (rowCount, dbDir);
rowStats.add (time);
}
}
for (final Entry<String, List<Long>> statsEntry : stats.entrySet ()) {
String label = statsEntry.getKey ();
double sum = 0;
final List<Long> data = statsEntry.getValue ();
for (Long time : data) {
sum += time;
}
System.out.println ("[" + System.getProperty ("h2.javaObjectSerializer") + "] execution average time: "
+ (sum / data.size ()) + "ms for " + label + " rows (" + samplesCount + " executions)");
}
}
private static void executeUserDriven (final File dbDir) throws Exception {
final Scanner scanner = new Scanner (System.in);
while (askRowCount (scanner)) {
try {
final int rowCount = scanner.nextInt ();
long time = new Main ().work (rowCount, dbDir);
System.out.println ("Execution time: " + time + "ms for " + rowCount + " rows");
} catch (final InputMismatchException e) {
final String cmd = scanner.nextLine ();
if ("q".equalsIgnoreCase (cmd)) {
return;
}
}
}
}
private static boolean askRowCount (final Scanner scanner) {
System.out.println ("Please provide the number of rows to insert, then hit ENTER:");
return scanner.hasNextInt ();
}
private long work (final int rowCount, final File dbDir) throws Exception {
final long startTime = System.currentTimeMillis ();
dbDir.mkdirs ();
dbDir.deleteOnExit ();
Class.forName ("org.h2.Driver");
url = "jdbc:h2:" + dbDir.getCanonicalPath () + "/data";
withDb (new JdbcTemplate () {
@Override
public void execute (final Connection c) throws SQLException {
final Statement statement = c.createStatement ();
try {
statement
.execute ("CREATE TABLE IF NOT EXISTS mydata (id LONG PRIMARY KEY AUTO_INCREMENT, data OTHER );");
statement.execute ("TRUNCATE TABLE mydata;");
} finally {
statement.close ();
}
}
});
final List<List<Calendar>> originalData = new ArrayList<List<Calendar>> ();
withDb (new JdbcTemplate () {
@Override
public void execute (final Connection c) throws SQLException {
final PreparedStatement stmt = c.prepareStatement ("INSERT INTO mydata(data) values (?)");
try {
final int calendarCount = CALENDAR_COUNT;
for (int row = 0; row < rowCount; row++) {
final List<Calendar> data = new LinkedList<Calendar> ();
originalData.add (data);
for (int i = 0; i < calendarCount; i++) {
final Calendar calendar = new GregorianCalendar (row, 0, 0, 0, 0, i);
data.add (calendar);
}
stmt.setObject (1, data);
stmt.addBatch ();
}
stmt.executeBatch ();
} finally {
stmt.close ();
}
}
});
withDb (new JdbcTemplate () {
@Override
public void execute (final Connection c) throws SQLException {
final PreparedStatement stmt = c.prepareStatement ("SELECT * FROM mydata");
try {
final ResultSet rs = stmt.executeQuery ();
try {
final List<List<Calendar>> actualData = new ArrayList<List<Calendar>> ();
while (rs.next ()) {
// final Object idValue = rs.getObject (1);
final Object dataValue = rs.getObject (2);
// System.out.print (idValue);
// System.out.print ("\t\t");
// System.out.println (dataValue);
actualData.add ((List<Calendar>) dataValue);
}
/*
* data consistency check
*/
if (!actualData.equals (originalData)) {
throw new RuntimeException ("data corruption! originalData: " + originalData
+ "\nactualData: " + actualData);
}
} finally {
rs.close ();
}
} finally {
stmt.close ();
}
}
});
return System.currentTimeMillis () - startTime;
}
private void withDb (final JdbcTemplate jdbcTemplate) throws SQLException {
final Connection c = DriverManager.getConnection (url, "sa", "sa");
try {
jdbcTemplate.execute (c);
} finally {
c.close ();
}
}
static interface JdbcTemplate {
void execute (Connection c) throws SQLException;
}
public static class KryoSerializer implements JavaObjectSerializer {
final Kryo kryo = new Kryo ();
@Override
public byte[] serialize (final Object obj) throws Exception {
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream ();
final Output output = new Output (byteArrayOutputStream);
try {
kryo.writeClassAndObject (output, obj);
} finally {
output.close ();
}
return byteArrayOutputStream.toByteArray ();
}
@Override
public Object deserialize (final byte[] bytes) throws Exception {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream (bytes);
final Input input = new Input (byteArrayInputStream);
try {
return kryo.readClassAndObject (input);
} finally {
input.close ();
}
}
}
public static class JBossSerializer implements JavaObjectSerializer {
@Override
public byte[] serialize (final Object obj) throws Exception {
final ByteArrayOutputStream baos = new ByteArrayOutputStream ();
try {
final ObjectOutputStream oos = new JBossObjectOutputStream (baos);
try {
oos.writeObject (obj);
oos.flush ();
} finally {
oos.close ();
}
} finally {
baos.close ();
}
return baos.toByteArray ();
}
@Override
public Object deserialize (final byte[] bytes) throws Exception {
final ByteArrayInputStream bais = new ByteArrayInputStream (bytes);
try {
final ObjectInputStream ois = new JBossObjectInputStream (bais);
try {
return ois.readObject ();
} finally {
ois.close ();
}
} finally {
bais.close ();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment