· 6 years ago · Aug 06, 2019, 02:36 AM
1import java.io.ByteArrayInputStream;
2import java.io.ByteArrayOutputStream;
3import java.io.File;
4import java.io.ObjectInputStream;
5import java.io.ObjectOutputStream;
6import java.sql.Connection;
7import java.sql.DriverManager;
8import java.sql.PreparedStatement;
9import java.sql.ResultSet;
10import java.sql.SQLException;
11import java.sql.Statement;
12import java.util.ArrayList;
13import java.util.Calendar;
14import java.util.GregorianCalendar;
15import java.util.InputMismatchException;
16import java.util.LinkedHashMap;
17import java.util.LinkedList;
18import java.util.List;
19import java.util.Map;
20import java.util.Map.Entry;
21import java.util.Scanner;
22
23import org.h2.api.JavaObjectSerializer;
24import org.jboss.serial.io.JBossObjectInputStream;
25import org.jboss.serial.io.JBossObjectOutputStream;
26
27import com.esotericsoftware.kryo.Kryo;
28import com.esotericsoftware.kryo.io.Input;
29import com.esotericsoftware.kryo.io.Output;
30
31public class Main {
32
33 private static final int STEP = 10;
34 private static final int SAMPLES_COUNT = 10;
35 private static final int MAX_ROWS = 10000;
36 private static final int CALENDAR_COUNT = 50;
37 private String url;
38
39 public static void main (final String[] args) throws Exception {
40 final File dbDir = new File (System.getProperty ("java.io.tmpdir"), "h2perftest");
41// executeUserDriven (dbDIr);
42 acquireStats (dbDir);
43 }
44
45 private static void acquireStats (final File dbDir) throws Exception {
46 final int samplesCount = SAMPLES_COUNT;
47 final Map<String, List<Long>> stats = new LinkedHashMap<String, List<Long>> ();
48 final int maxRows = MAX_ROWS;
49 for (int rowCount = 1; rowCount <= maxRows; rowCount = rowCount * STEP) {
50 List<Long> rowStats = new LinkedList<Long> ();
51 stats.put (Integer.toString (rowCount), rowStats);
52 for (int sampleNum = 0; sampleNum < samplesCount; sampleNum++) {
53 Main main = new Main ();
54 long time = main.work (rowCount, dbDir);
55 rowStats.add (time);
56 }
57 }
58 for (final Entry<String, List<Long>> statsEntry : stats.entrySet ()) {
59 String label = statsEntry.getKey ();
60 double sum = 0;
61
62 final List<Long> data = statsEntry.getValue ();
63 for (Long time : data) {
64 sum += time;
65 }
66 System.out.println ("[" + System.getProperty ("h2.javaObjectSerializer") + "] execution average time: "
67 + (sum / data.size ()) + "ms for " + label + " rows (" + samplesCount + " executions)");
68 }
69 }
70
71 private static void executeUserDriven (final File dbDir) throws Exception {
72 final Scanner scanner = new Scanner (System.in);
73 while (askRowCount (scanner)) {
74 try {
75
76 final int rowCount = scanner.nextInt ();
77 long time = new Main ().work (rowCount, dbDir);
78 System.out.println ("Execution time: " + time + "ms for " + rowCount + " rows");
79
80 } catch (final InputMismatchException e) {
81 final String cmd = scanner.nextLine ();
82 if ("q".equalsIgnoreCase (cmd)) {
83 return;
84 }
85 }
86 }
87 }
88
89 private static boolean askRowCount (final Scanner scanner) {
90 System.out.println ("Please provide the number of rows to insert, then hit ENTER:");
91 return scanner.hasNextInt ();
92 }
93
94 private long work (final int rowCount, final File dbDir) throws Exception {
95 final long startTime = System.currentTimeMillis ();
96
97 dbDir.mkdirs ();
98 dbDir.deleteOnExit ();
99
100 Class.forName ("org.h2.Driver");
101 url = "jdbc:h2:" + dbDir.getCanonicalPath () + "/data";
102
103 withDb (new JdbcTemplate () {
104 @Override
105 public void execute (final Connection c) throws SQLException {
106 final Statement statement = c.createStatement ();
107 try {
108 statement
109 .execute ("CREATE TABLE IF NOT EXISTS mydata (id LONG PRIMARY KEY AUTO_INCREMENT, data OTHER );");
110 statement.execute ("TRUNCATE TABLE mydata;");
111 } finally {
112 statement.close ();
113 }
114
115 }
116 });
117
118 final List<List<Calendar>> originalData = new ArrayList<List<Calendar>> ();
119
120 withDb (new JdbcTemplate () {
121 @Override
122 public void execute (final Connection c) throws SQLException {
123 final PreparedStatement stmt = c.prepareStatement ("INSERT INTO mydata(data) values (?)");
124 try {
125 final int calendarCount = CALENDAR_COUNT;
126 for (int row = 0; row < rowCount; row++) {
127 final List<Calendar> data = new LinkedList<Calendar> ();
128 originalData.add (data);
129 for (int i = 0; i < calendarCount; i++) {
130 final Calendar calendar = new GregorianCalendar (row, 0, 0, 0, 0, i);
131 data.add (calendar);
132 }
133 stmt.setObject (1, data);
134 stmt.addBatch ();
135 }
136 stmt.executeBatch ();
137 } finally {
138 stmt.close ();
139 }
140
141 }
142 });
143
144 withDb (new JdbcTemplate () {
145 @Override
146 public void execute (final Connection c) throws SQLException {
147 final PreparedStatement stmt = c.prepareStatement ("SELECT * FROM mydata");
148 try {
149 final ResultSet rs = stmt.executeQuery ();
150 try {
151 final List<List<Calendar>> actualData = new ArrayList<List<Calendar>> ();
152 while (rs.next ()) {
153// final Object idValue = rs.getObject (1);
154 final Object dataValue = rs.getObject (2);
155// System.out.print (idValue);
156// System.out.print ("\t\t");
157// System.out.println (dataValue);
158
159 actualData.add ((List<Calendar>) dataValue);
160 }
161
162 /*
163 * data consistency check
164 */
165 if (!actualData.equals (originalData)) {
166 throw new RuntimeException ("data corruption! originalData: " + originalData
167 + "\nactualData: " + actualData);
168 }
169 } finally {
170 rs.close ();
171 }
172 } finally {
173 stmt.close ();
174 }
175
176 }
177 });
178
179 return System.currentTimeMillis () - startTime;
180
181 }
182
183 private void withDb (final JdbcTemplate jdbcTemplate) throws SQLException {
184 final Connection c = DriverManager.getConnection (url, "sa", "sa");
185
186 try {
187 jdbcTemplate.execute (c);
188 } finally {
189 c.close ();
190 }
191
192 }
193
194 static interface JdbcTemplate {
195 void execute (Connection c) throws SQLException;
196 }
197
198 public static class KryoSerializer implements JavaObjectSerializer {
199
200 final Kryo kryo = new Kryo ();
201
202 @Override
203 public byte[] serialize (final Object obj) throws Exception {
204 final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream ();
205 final Output output = new Output (byteArrayOutputStream);
206 try {
207 kryo.writeClassAndObject (output, obj);
208 } finally {
209 output.close ();
210 }
211 return byteArrayOutputStream.toByteArray ();
212 }
213
214 @Override
215 public Object deserialize (final byte[] bytes) throws Exception {
216 final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream (bytes);
217 final Input input = new Input (byteArrayInputStream);
218 try {
219 return kryo.readClassAndObject (input);
220 } finally {
221 input.close ();
222 }
223 }
224
225 }
226
227 public static class JBossSerializer implements JavaObjectSerializer {
228
229 @Override
230 public byte[] serialize (final Object obj) throws Exception {
231 final ByteArrayOutputStream baos = new ByteArrayOutputStream ();
232 try {
233 final ObjectOutputStream oos = new JBossObjectOutputStream (baos);
234 try {
235 oos.writeObject (obj);
236 oos.flush ();
237 } finally {
238 oos.close ();
239 }
240 } finally {
241 baos.close ();
242 }
243 return baos.toByteArray ();
244 }
245
246 @Override
247 public Object deserialize (final byte[] bytes) throws Exception {
248 final ByteArrayInputStream bais = new ByteArrayInputStream (bytes);
249 try {
250 final ObjectInputStream ois = new JBossObjectInputStream (bais);
251 try {
252 return ois.readObject ();
253 } finally {
254 ois.close ();
255 }
256 } finally {
257 bais.close ();
258 }
259 }
260
261 }
262}