~ubuntu-branches/ubuntu/trusty/mysql-5.6/trusty

« back to all changes in this revision

Viewing changes to storage/ndb/clusterj/clusterj-jpatest/src/main/java/com/mysql/clusterj/jpatest/Driver.java

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-02-12 11:54:27 UTC
  • Revision ID: package-import@ubuntu.com-20140212115427-oq6tfsqxl1wuwehi
Tags: upstream-5.6.15
ImportĀ upstreamĀ versionĀ 5.6.15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
36
/**
 
37
 * This class is part of the CRUND benchmark that measures standard database operations 
 
38
 * over a series of transactions on an increasing data set.
 
39
 * <p>
 
40
 * The abstract database operations are variations of: Create,
 
41
 * Read, Update, Navigate, and Delete -- hence, the benchmark's name: CRUND.
 
42
 * <p>
 
43
 * The actual operations are defined by subclasses to allow measuring the
 
44
 * operation performance across different datastore implementations.
 
45
 *
 
46
 * @see <a href="http://www.urbandictionary.com/define.php?term=crund">Urban Dictionary: crund</a>
 
47
 * <ol>
 
48
 * <li> used to debase people who torture others with their illogical
 
49
 * attempts to make people laugh;
 
50
 * <li> reference to cracking obsolete jokes;
 
51
 * <li> a dance form;
 
52
 * <li> to hit hard or smash.
 
53
 * </ol>
 
54
 */
 
55
abstract public class Driver {
 
56
 
 
57
    /**
 
58
     *  The stream to write messages to.
 
59
     */
 
60
    static protected final PrintWriter out = new PrintWriter(System.out, true);
 
61
 
 
62
    /**
 
63
     *  The stream to write error messages to.
 
64
     */
 
65
    static protected final PrintWriter err = new PrintWriter(System.err, true);
 
66
 
 
67
    /**
 
68
     *  Shortcut to the end-of-line character sequence.
 
69
     */
 
70
    static protected final String endl = System.getProperty("line.separator");
 
71
 
 
72
    /**
 
73
     *  Shortcut to the Runtime.
 
74
     */
 
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
 
 
106
    /**
 
107
     * A database operation to be benchmarked.
 
108
     */
 
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
 
 
123
    /**
 
124
     * The list of database operations to be benchmarked.
 
125
     * While the list instance is final, its content is managed by methods
 
126
     * initOperations() and closeOperations() as defined by subclasses.
 
127
     */
 
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
 
 
151
    /**
 
152
     * Reports an error if a condition is not met.
 
153
     *
 
154
     * An invariant method to ensure the consistent application
 
155
     * of verifying read results.
 
156
     */
 
157
    static protected final void verify(boolean cond) {
 
158
        //assert (cond);
 
159
        if (!cond)
 
160
            throw new RuntimeException("wrong data; verification failed");
 
161
    }
 
162
 
 
163
    /**
 
164
     * Loads a dynamically linked system library and reports any failures.
 
165
     */
 
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
 
 
191
    /**
 
192
     * Runs the entire benchmark.
 
193
     */
 
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
 
 
239
    /**
 
240
     * Initializes the benchmark's resources.
 
241
     */
 
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
 
 
255
    /**
 
256
     * Releases the benchmark's resources.
 
257
     */
 
258
    protected void close() throws Exception {
 
259
        // close log buffers
 
260
        header = null;
 
261
        rtimes = null;
 
262
        musage = null;
 
263
 
 
264
        closeLogFile();
 
265
    }
 
266
 
 
267
    /**
 
268
     * Loads the benchmark's properties from properties files.
 
269
     * Keys might appear multiple times in the same or different files.
 
270
     * If there are duplicate keys, the last key definition overrides any
 
271
     * previous value for the same key in the same or different file.
 
272
     */
 
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
 
 
294
    /**
 
295
     * Retrieves a property's value and parses it as a boolean.
 
296
     */
 
297
    protected boolean parseBoolean(String k) {
 
298
        return Boolean.parseBoolean(props.getProperty(k));
 
299
    }
 
300
    
 
301
    /**
 
302
     * Retrieves a property's value and parses it as a signed decimal integer.
 
303
     * @throws NumberFormatException with a descriptive error message
 
304
     */
 
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
    
 
318
    /**
 
319
     * Initializes the benchmark properties.
 
320
     */
 
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
 
 
347
    /**
 
348
     * Prints the benchmark's properties.
 
349
     */
 
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
 
 
373
    /**
 
374
     * Opens the benchmark's data log file.
 
375
     */
 
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
 
 
382
    /**
 
383
     * Closes the benchmark's data log file.
 
384
     */
 
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
 
 
397
    /**
 
398
     * Runs a series of benchmark operations on scaled-up data.
 
399
     */
 
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
 
 
426
    /**
 
427
     * Runs a series of benchmark operations.
 
428
     */
 
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
 
 
495
    /**
 
496
     * Runs a benchmark operation.
 
497
     */
 
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
 
 
507
    /**
 
508
     * Begins a benchmarked transaction.
 
509
     */
 
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
 
 
529
    /**
 
530
     * Closes a benchmarked transaction.
 
531
     */
 
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
 
 
575
    /**
 
576
     * Attempts to run the JVM's Garbage Collector.
 
577
     */
 
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
 
 
600
    /**
 
601
     * Prints a command-line usage message and exits.
 
602
     */
 
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
 
 
612
    /**
 
613
     * Parses the benchmark's command-line arguments.
 
614
     */
 
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
 
 
637
    /** Clears the propFileNames from a previous run
 
638
     *
 
639
     */
 
640
    public static void clearPropFileNames() {
 
641
        propFileNames.clear();
 
642
    }
 
643
 
 
644
}