run-octane.js revision 877:cf4d2252d444
1/*
2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/**
25 * @subtest
26 */
27
28
29function initZlib() {
30    zlib = new BenchmarkSuite('zlib', [152815148], [
31                            new Benchmark('zlib', false, true, 10,
32                                  runZlib, undefined, tearDownZlib, null, 3)]);
33}
34
35var tests = [
36    {name:"box2d",         files:["box2d.js"],                         suite:"Box2DBenchmark"},
37    {name:"code-load",     files:["code-load.js"],                     suite:"CodeLoad"},
38    {name:"crypto",        files:["crypto.js"],                        suite:"Crypto"},
39    {name:"deltablue",     files:["deltablue.js"],                     suite:"DeltaBlue"},
40    {name:"earley-boyer",  files:["earley-boyer.js"],                  suite:"EarleyBoyer"},
41    {name:"gbemu",         files:["gbemu-part1.js", "gbemu-part2.js"], suite:"GameboyBenchmark"},
42    {name:"mandreel",      files:["mandreel.js"],                      suite:"MandreelBenchmark"},
43    {name:"navier-stokes", files:["navier-stokes.js"],                 suite:"NavierStokes"},
44    {name:"pdfjs",         files:["pdfjs.js"],                         suite:"PdfJS"},
45    {name:"raytrace",      files:["raytrace.js"],                      suite:"RayTrace"},
46    {name:"regexp",        files:["regexp.js"],                        suite:"RegExpSuite"},
47    {name:"richards",      files:["richards.js"],                      suite:"Richards"},
48    {name:"splay",         files:["splay.js"],                         suite:"Splay"},
49    {name:"typescript",    files:["typescript.js", "typescript-input.js", "typescript-compiler.js"], suite:"typescript"},
50    //zlib currently disabled - requires read
51    {name:"zlib",          files:["zlib.js", "zlib-data.js"], suite:"zlib", before:initZlib}
52];
53var dir = (typeof(__DIR__) == 'undefined') ? "test/script/basic/" : __DIR__;
54
55// TODO: why is this path hard coded when it's defined in project properties?
56var path = dir + "../external/octane/";
57
58var runtime = undefined;
59var verbose = false;
60
61var numberOfIterations = 5;
62
63function endsWith(str, suffix) {
64    return str.indexOf(suffix, str.length - suffix.length) !== -1;
65}
66
67function should_compile_only(name) {
68    return (typeof compile_only !== 'undefined')
69}
70
71function load_bench(arg) {
72
73    for (var idx = 0; idx < arg.files.length; idx++) {
74    var f = arg.files[idx];
75    var file = f.split('/');
76    var file_name = path + file[file.length - 1];
77
78    var compile_and_return = should_compile_only(file_name);
79    if (compile_and_return) {
80        if (typeof compile_only === 'undefined') { //for a run, skip compile onlies, don't even compile them
81        return true;
82        }
83    }
84
85    print_verbose(arg, "loading '" + arg.name + "' [" + f + "]...");
86    load(file_name);
87    }
88
89    if (typeof arg.before !== 'undefined') {
90    arg.before();
91    }
92
93    if (compile_and_return) {
94    print_always(arg, "Compiled OK");
95    }
96    return !compile_and_return;
97
98}
99
100
101function run_one_benchmark(arg, iters) {
102
103    if (!load_bench(arg)) {
104    return;
105    }
106
107    var success = true;
108    var current_name;
109
110    if (iters == undefined) {
111    iters = numberOfIterations;
112    } else {
113    numberOfIterations = iters;
114    }
115
116    var benchmarks = eval(arg.suite + ".benchmarks");
117    var min_score  = 1e9;
118    var max_score  = 0;
119    var mean_score = 0;
120
121    try {
122    for (var x = 0; x < benchmarks.length ; x++) {
123        //do warmup run
124        //reset random number generator needed as of octane 9 before each run
125        BenchmarkSuite.ResetRNG();
126        benchmarks[x].Setup();
127    }
128    BenchmarkSuite.ResetRNG();
129    print_verbose(arg, "running '" + arg.name + "' for " + iters + " iterations of no less than " + min_time + " seconds");
130
131    var scores = [];
132
133    var min_time_ms = min_time * 1000;
134    var len = benchmarks.length;
135
136    for (var it = 0; it < iters + 1; it++) {
137        //every iteration must take a minimum of 10 secs
138        var ops = 0;
139        var elapsed = 0;
140        var start = new Date;
141        do {
142        for (var i = 0; i < len; i++) {
143            benchmarks[i].run();
144            //important - no timing here like elapsed = new Date() - start, as in the
145            //original harness. This will make timing very non-deterministic.
146            //NOTHING else must live in this loop
147        }
148        ops += len;
149        elapsed = new Date - start;
150        } while (elapsed < min_time * 1000);
151
152        var score = ops / elapsed * 1000 * 60;
153        scores.push(score);
154        var name = it == 0 ? "warmup" : "iteration " + it;
155        print_verbose(arg, name + " finished " + score.toFixed(0) + " ops/minute");
156    }
157
158    for (var x = 0; x < benchmarks.length ; x++) {
159        benchmarks[x].TearDown();
160    }
161
162    for (var x = 1; x < iters + 1 ; x++) {
163        mean_score += scores[x];
164        min_score = Math.min(min_score, scores[x]);
165        max_score = Math.max(max_score, scores[x]);
166    }
167    mean_score /= iters;
168    } catch (e) {
169    print_always(arg, "*** Aborted and setting score to zero. Reason: " + e);
170    if (e instanceof java.lang.Throwable) {
171        e.printStackTrace();
172    }
173    mean_score = min_score = max_score = 0;
174    scores = [0];
175    }
176
177    var res = mean_score.toFixed(0);
178    if (verbose) {
179    res += " ops/minute (" + min_score.toFixed(0) + "-" + max_score.toFixed(0) + "), warmup=" + scores[0].toFixed(0);
180    }
181    print_always(arg, res);
182}
183
184function runtime_string() {
185    return runtime == undefined ? "" : ("[" + runtime + "] ");
186}
187
188function print_always(arg, x) {
189    print(runtime_string() + "[" + arg.name + "] " + x);
190}
191
192function print_verbose(arg, x) {
193    if (verbose) {
194    print_always(arg, x)
195    }
196}
197
198function run_suite(tests, iters) {
199    for (var idx = 0; idx < tests.length; idx++) {
200    run_one_benchmark(tests[idx], iters);
201    }
202}
203
204var args = [];
205
206if (typeof $ARGS !== 'undefined') {
207    args = $ARGS;
208} else if (typeof arguments !== 'undefined' && arguments.length != 0) {
209    args = arguments;
210}
211
212var new_args = [];
213for (i in args) {
214    if (args[i].toString().indexOf(' ') != -1) {
215    args[i] = args[i].replace(/\/$/, '');
216    var s = args[i].split(' ');
217    for (j in s) {
218        new_args.push(s[j]);
219    }
220    } else {
221    new_args.push(args[i]);
222    }
223}
224
225if (new_args.length != 0) {
226    args = new_args;
227}
228
229var tests_found = [];
230var iters = undefined;
231var min_time = 5;
232
233for (var i = 0; i < args.length; i++) {
234    arg = args[i];
235    if (arg == "--iterations") {
236    iters = +args[++i];
237    if (isNaN(iters)) {
238        throw "'--iterations' must be followed by integer";
239    }
240    } else if (arg == "--runtime") {
241    runtime = args[++i];
242    } else if (arg == "--verbose") {
243    verbose = true;
244    } else if (arg == "--min-time") {
245    min_time = +args[++i];
246    if (isNaN(iters)) {
247        throw "'--min-time' must be followed by integer";
248    }
249    } else if (arg == "") {
250    continue; //skip
251    } else {
252    var found = false;
253    for (j in tests) {
254        if (tests[j].name === arg) {
255        tests_found.push(tests[j]);
256        found = true;
257        break;
258        }
259    }
260    if (!found) {
261        var str = "unknown test name: '" + arg + "' -- valid names are: ";
262        for (j in tests) {
263        if (j != 0) {
264            str += ", ";
265        }
266        str += "'" + tests[j].name + "'";
267        }
268        throw str;
269    }
270    }
271}
272
273if (tests_found.length == 0) {
274    for (i in tests) {
275    tests_found.push(tests[i]);
276    }
277}
278
279// returns false for rhino, v8 and all other javascript runtimes, true for Nashorn
280function is_this_nashorn() {
281    return typeof Error.dumpStack == 'function'
282}
283
284if (is_this_nashorn()) {
285    try {
286    read = readFully;
287    } catch (e) {
288    print("ABORTING: Cannot find 'readFully'. You must have scripting enabled to use this test harness. (-scripting)");
289    throw e;
290    }
291}
292
293// run tests in alphabetical order by name
294tests_found.sort(function(a, b) {
295    if (a.name < b.name) {
296    return -1;
297    } else if (a.name > b.name) {
298    return 1;
299    } else {
300    return 0;
301    }
302});
303
304load(path + 'base.js');
305run_suite(tests_found, iters);
306