MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Driver.java
1 /*
2  Copyright 2010 Sun Microsystems, Inc.
3  All rights reserved. Use is subject to license terms.
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; version 2 of the License.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 package com.mysql.clusterj.jpatest;
20 
21 import java.util.Properties;
22 import java.util.List;
23 import java.util.Set;
24 import java.util.HashSet;
25 import java.util.ArrayList;
26 import java.util.Date;
27 import java.text.SimpleDateFormat;
28 
29 import java.io.FileInputStream;
30 import java.io.FileWriter;
31 import java.io.IOException;
32 import java.io.PrintWriter;
33 import java.io.InputStream;
34 
35 
55 abstract public class Driver {
56 
60  static protected final PrintWriter out = new PrintWriter(System.out, true);
61 
65  static protected final PrintWriter err = new PrintWriter(System.err, true);
66 
70  static protected final String endl = System.getProperty("line.separator");
71 
75  static private final Runtime rt = Runtime.getRuntime();
76 
77  // command-line arguments
78  static private final List<String> propFileNames = new ArrayList<String>();
79  static private String logFileName
80  = ("log_"
81  + new SimpleDateFormat("yyyyMMdd_HHMMss").format(new Date())
82  + ".txt");
83 
84  // the data output writer
85  private PrintWriter log;
86 
87  // benchmark settings
88  protected final Properties props = new Properties();
89  protected String descr = "";
90  protected boolean logRealTime = false;
91  protected boolean logMemUsage = false;
92  protected boolean includeFullGC = false;
93  protected boolean logSumOfOps = false;
94  protected boolean renewOperations = false;
95  protected boolean renewConnection = false;
96  protected boolean allowExtendedPC = false;
97  protected int aStart = (1 << 8), aEnd = (1 << 12), aIncr = (1 << 2);
98  protected int bStart = (1 << 8), bEnd = (1 << 12), bIncr = (1 << 2);
99  protected int maxStringLength = 100;
100  protected int warmupRuns = 0;
101  protected int hotRuns = 0;
102  protected final Set<String> exclude = new HashSet<String>();
103 
104  // ----------------------------------------------------------------------
105 
109  protected abstract class Op {
110  final protected String name;
111 
112  public Op(String name) {
113  this.name = name;
114  }
115 
116  public String getName() {
117  return name;
118  }
119 
120  public abstract void run(int countA, int countB) throws Exception;
121  };
122 
128  protected final List<Op> ops = new ArrayList<Op>();
129 
130  // buffers collecting the header and data lines written to log
131  boolean logHeader;
132  private StringBuilder header;
133  private StringBuilder rtimes;
134  private StringBuilder musage;
135 
136  // benchmark data fields
137  private long t0 = 0, t1 = 0, ta = 0;
138  private long m0 = 0, m1 = 0, ma = 0;
139 
140  // benchmark methods to be defined by subclasses
141  abstract protected void initConnection() throws Exception;
142  abstract protected void closeConnection() throws Exception;
143  abstract protected void initOperations() throws Exception;
144  abstract protected void closeOperations() throws Exception;
145  abstract protected void clearPersistenceContext() throws Exception;
146  abstract protected void clearData() throws Exception;
147  abstract protected void beginTransaction() throws Exception;
148  abstract protected void commitTransaction() throws Exception;
149  abstract protected void rollbackTransaction() throws Exception;
150 
157  static protected final void verify(boolean cond) {
158  //assert (cond);
159  if (!cond)
160  throw new RuntimeException("wrong data; verification failed");
161  }
162 
166  static protected void loadSystemLibrary(String name) {
167  out.print("loading libary ...");
168  out.flush();
169  try {
170  System.loadLibrary(name);
171  } catch (UnsatisfiedLinkError e) {
172  String path;
173  try {
174  path = System.getProperty("java.library.path");
175  } catch (Exception ex) {
176  path = "<exception caught: " + ex.getMessage() + ">";
177  }
178  err.println("NdbBase: failed loading library '"
179  + name + "'; java.library.path='" + path + "'");
180  throw e;
181  } catch (SecurityException e) {
182  err.println("NdbBase: failed loading library '"
183  + name + "'; caught exception: " + e);
184  throw e;
185  }
186  out.println(" [" + name + "]");
187  }
188 
189  // ----------------------------------------------------------------------
190 
194  public void run() {
195  try {
196  init();
197 
198  // warmup runs
199  for (int i = 0; i < warmupRuns; i++)
200  runTests();
201 
202  // truncate log file, reset log buffers
203  out.println();
204  out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
205  out.println("start logging results ...");
206  out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
207  out.println();
208  header = new StringBuilder();
209  rtimes = new StringBuilder();
210  musage = new StringBuilder();
211  closeLogFile();
212  openLogFile();
213 
214  // hot runs
215  for (int i = 0; i < hotRuns; i++)
216  runTests();
217 
218  // write log buffers
219  if (logRealTime) {
220  log.println(descr + ", rtime[ms]"
221  + header.toString() + endl
222  + rtimes.toString() + endl + endl + endl);
223  }
224  if (logMemUsage) {
225  log.println(descr + ", net musage[KiB]"
226  + header.toString() + endl
227  + musage.toString() + endl + endl + endl);
228  }
229 
230  close();
231  } catch (Exception ex) {
232  // end the program regardless of threads
233  out.println("caught " + ex);
234  ex.printStackTrace();
235  System.exit(2); // return an error code
236  }
237  }
238 
242  protected void init() throws Exception {
243  loadProperties();
244  initProperties();
245  printProperties();
246  openLogFile();
247 
248  // init log buffers
249  logHeader = true;
250  header = new StringBuilder();
251  rtimes = new StringBuilder();
252  musage = new StringBuilder();
253  }
254 
258  protected void close() throws Exception {
259  // close log buffers
260  header = null;
261  rtimes = null;
262  musage = null;
263 
264  closeLogFile();
265  }
266 
273  private void loadProperties() throws IOException {
274  if (propFileNames.size() == 0) {
275  propFileNames.add("crund.properties");
276  }
277 
278  out.println();
279  for (String fn : propFileNames) {
280  out.println("reading properties file: " + fn);
281  InputStream is = null;
282  try {
283  is = new FileInputStream(fn);
284  props.load(is);
285  } catch (Exception e) {
286  out.println("error reading file.");
287  } finally {
288  if (is != null)
289  is.close();
290  }
291  }
292  }
293 
297  protected boolean parseBoolean(String k) {
298  return Boolean.parseBoolean(props.getProperty(k));
299  }
300 
305  protected int parseInt(String k, int vdefault) {
306  final String v = props.getProperty(k);
307  try {
308  return (v == null ? vdefault : Integer.parseInt(v));
309  } catch (NumberFormatException e) {
310  final NumberFormatException nfe = new NumberFormatException(
311  "invalid value of benchmark property ('" + k + "', '"
312  + v + "').");
313  nfe.initCause(e);
314  throw nfe;
315  }
316  }
317 
321  protected void initProperties() {
322  // initialize boolean/numeric properties
323  logRealTime = parseBoolean("logRealTime");
324  logMemUsage = parseBoolean("logMemUsage");
325  includeFullGC = parseBoolean("includeFullGC");
326  logSumOfOps = parseBoolean("logSumOfOps");
327  renewOperations = parseBoolean("renewOperations");
328  renewConnection = parseBoolean("renewConnection");
329  allowExtendedPC = parseBoolean("allowExtendedPC");
330  aStart = parseInt("aStart", 1 << 8);
331  aEnd = parseInt("aEnd", 1 << 12);
332  aIncr = parseInt("aIncr", 1 << 2);
333  bStart = parseInt("bStart", 1 << 8);
334  bEnd = parseInt("bEnd", 1 << 12);
335  bIncr = parseInt("bIncr", 1 << 2);
336  maxStringLength = parseInt("maxStringLength", 100);
337  warmupRuns = parseInt("warmupRuns", 0);
338  hotRuns = parseInt("hotRuns", 1);
339 
340  // initialize exclude set
341  final String[] e = props.getProperty("exclude", "").split(",");
342  for (int i = 0; i < e.length; i++) {
343  exclude.add(e[i]);
344  }
345  }
346 
350  protected void printProperties() {
351  //props.list(out);
352  out.println();
353  out.println("main settings:");
354  out.println("logRealTime: " + logRealTime);
355  out.println("logMemUsage: " + logMemUsage);
356  out.println("includeFullGC: " + includeFullGC);
357  out.println("logSumOfOps: " + logSumOfOps);
358  out.println("renewOperations: " + renewOperations);
359  out.println("renewConnection: " + renewConnection);
360  out.println("allowExtendedPC: " + allowExtendedPC);
361  out.println("aStart: " + aStart);
362  out.println("aEnd: " + aEnd);
363  out.println("aIncr: " + aIncr);
364  out.println("bStart: " + bStart);
365  out.println("bEnd: " + bEnd);
366  out.println("bIncr: " + bIncr);
367  out.println("maxStringLength: " + maxStringLength);
368  out.println("warmupRuns: " + warmupRuns);
369  out.println("hotRuns: " + hotRuns);
370  out.println("exclude: " + exclude);
371  }
372 
376  private void openLogFile() throws IOException {
377  out.println();
378  out.println("writing results to file: " + logFileName);
379  log = new PrintWriter(new FileWriter(logFileName, false));
380  }
381 
385  private void closeLogFile() throws IOException {
386  out.print("closing files ... ");
387  out.flush();
388  if (log != null) {
389  log.close();
390  log = null;
391  }
392  out.println(" [ok]");
393  }
394 
395  // ----------------------------------------------------------------------
396 
400  protected void runTests() throws Exception {
401  initConnection();
402  initOperations();
403 
404  for (int i = aStart; i <= aEnd; i *= aIncr) {
405  //for (int j = bBeg; j <= bEnd; j *= bIncr)
406  for (int j = (i > bStart ? i : bStart); j <= bEnd; j *= bIncr) {
407  try {
408  runOperations(i, j);
409  } catch (Exception ex) {
410  // already in rollback for database/orm exceptions
411  //rollbackTransaction();
412  throw ex;
413  }
414  }
415  }
416 
417  out.println();
418  out.println("------------------------------------------------------------");
419  out.println();
420 
421  clearData();
422  closeOperations();
423  closeConnection();
424  }
425 
429  protected void runOperations(int countA, int countB) throws Exception {
430  out.println();
431  out.println("------------------------------------------------------------");
432  out.println("countA = " + countA + ", countB = " + countB);
433  out.println();
434 
435  // log buffers
436  if (logRealTime) {
437  rtimes.append("A=" + countA + ", B=" + countB);
438  ta = 0;
439  }
440  if (logMemUsage) {
441  musage.append("A=" + countA + ", B=" + countB);
442  ma = 0;
443  }
444 
445  // pre-run cleanup
446  if (renewConnection) {
447  closeOperations();
448  closeConnection();
449  initConnection();
450  initOperations();
451  } else if (renewOperations) {
452  closeOperations();
453  initOperations();
454  }
455  clearData();
456 
457  // run operations
458  for (Op op : ops) {
459  // pre-tx cleanup
460  if (!allowExtendedPC) {
461  // effectively prevent caching beyond Tx scope by clearing
462  // any data/result caches before the next transaction
463  clearPersistenceContext();
464  }
465  runOp(op, countA, countB);
466  }
467  if (logHeader) {
468  if (logSumOfOps)
469  header.append("\ttotal");
470  }
471 
472  // log buffers
473  logHeader = false;
474  if (logRealTime) {
475  if (logSumOfOps) {
476  rtimes.append("\t" + ta);
477  out.println();
478  out.println("total");
479  out.println("tx real time = " + ta + "\tms [begin..commit]");
480  }
481  rtimes.append(endl);
482  }
483  if (logMemUsage) {
484  if (logSumOfOps) {
485  musage.append("\t" + ma);
486  out.println();
487  out.println("total");
488  out.println("net mem usage = " + (ma >= 0 ? "+" : "") + ma
489  + "\tKiB");
490  }
491  musage.append(endl);
492  }
493  }
494 
498  protected void runOp(Op op, int countA, int countB) throws Exception {
499  final String name = op.getName();
500  if (!exclude.contains(name)) {
501  begin(name);
502  op.run(countA, countB);
503  commit(name);
504  }
505  }
506 
510  protected void begin(String name) throws Exception {
511  out.println();
512  out.println(name);
513 
514  // attempt max GC, before tx
515  gc();
516 
517  if (logMemUsage) {
518  m0 = rt.totalMemory() - rt.freeMemory();
519  }
520 
521  if (logRealTime) {
522  //t0 = System.currentTimeMillis();
523  t0 = System.nanoTime() / 1000000;
524  }
525 
526  beginTransaction();
527  }
528 
532  protected void commit(String name) throws Exception {
533  commitTransaction();
534 
535  // attempt one full GC, before timing tx end
536  if (includeFullGC) {
537  rt.gc();
538  }
539 
540  if (logRealTime) {
541  //t1 = System.currentTimeMillis();
542  t1 = System.nanoTime() / 1000000;
543  final long t = t1 - t0;
544  out.println("tx real time = " + t + "\tms [begin..commit]");
545  //rtimes.append("\t" + (Math.round(t / 100.0) / 10.0));
546  rtimes.append("\t" + t);
547  ta += t;
548  }
549 
550  if (logMemUsage) {
551  // attempt max GC, after tx
552  gc();
553  m1 = rt.totalMemory() - rt.freeMemory();
554  final long m0K = (m0 / 1024);
555  final long m1K = (m1 / 1024);
556  final long mK = m1K - m0K;
557  out.println("net mem usage = " + (mK >= 0 ? "+" : "") + mK
558  + "\tKiB [" + m0K + "K->" + m1K + "K]");
559 /*
560  out.println("allocated memory = "
561  + m1 + "\tK after commit");
562  out.println("total memory = "
563  + (rt.totalMemory() / 1024) + "\tK after commit");
564  out.println("max memory = "
565  + (rt.maxMemory() / 1024) + "\tK after commit");
566 */
567  musage.append("\t" + mK);
568  ma += mK;
569  }
570 
571  if (logHeader)
572  header.append("\t" + name);
573  }
574 
578  static private void gc() {
579  // empirically determined limit after which no further
580  // reduction in memory usage has been observed
581  //final int nFullGCs = 5;
582  final int nFullGCs = 10;
583  for (int i = 0; i < nFullGCs; i++) {
584  //out.print("gc: ");
585  long oldfree;
586  long newfree = rt.freeMemory();
587  do {
588  oldfree = newfree;
589  rt.runFinalization();
590  rt.gc();
591  newfree = rt.freeMemory();
592  //out.print('.');
593  } while (newfree > oldfree);
594  //out.println();
595  }
596  }
597 
598  // ----------------------------------------------------------------------
599 
603  static private void exitUsage() {
604  out.println("usage: [options]");
605  out.println(" [-p <file name>]... a properties file name");
606  out.println(" [-l <file name>] log file name for data output");
607  out.println(" [-h|--help] print usage message and exit");
608  out.println();
609  System.exit(1); // return an error code
610  }
611 
615  static public void parseArguments(String[] args) {
616  for (int i = 0; i < args.length; i++) {
617  final String arg = args[i];
618  if (arg.equals("-p")) {
619  if (i >= args.length) {
620  exitUsage();
621  }
622  propFileNames.add(args[++i]);
623  } else if (arg.equals("-l")) {
624  if (i >= args.length) {
625  exitUsage();
626  }
627  logFileName = args[++i];
628  } else if (arg.equals("-h") || arg.equals("--help")) {
629  exitUsage();
630  } else {
631  out.println("unknown option: " + arg);
632  exitUsage();
633  }
634  }
635  }
636 
640  public static void clearPropFileNames() {
641  propFileNames.clear();
642  }
643 
644 }