run-octane.js revision 848:e41798b06137
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
28var read;
29try {
30    read = readFully;
31} catch (e) {
32    print("ABORTING: Cannot find 'readFully'. You must have scripting enabled to use this test harness. (-scripting)");
33    throw e;
34}
35
36function initZlib() {
37    zlib = new BenchmarkSuite('zlib', [152815148], [
38						    new Benchmark('zlib', false, true, 10,
39								  runZlib, undefined, tearDownZlib, null, 3)]);
40}
41
42var tests = [
43    {name:"box2d",         files:["box2d.js"],                         suite:"Box2DBenchmark"},
44    {name:"code-load",     files:["code-load.js"],                     suite:"CodeLoad"},
45    {name:"crypto",        files:["crypto.js"],                        suite:"Crypto"},
46    {name:"deltablue",     files:["deltablue.js"],                     suite:"DeltaBlue"},
47    {name:"earley-boyer",  files:["earley-boyer.js"],                  suite:"EarleyBoyer"},
48    {name:"gbemu",         files:["gbemu-part1.js", "gbemu-part2.js"], suite:"GameboyBenchmark"},
49    {name:"mandreel",      files:["mandreel.js"],                      suite:"MandreelBenchmark"},
50    {name:"navier-stokes", files:["navier-stokes.js"],                 suite:"NavierStokes"},
51    {name:"pdfjs",         files:["pdfjs.js"],                         suite:"PdfJS"},
52    {name:"raytrace",      files:["raytrace.js"],                      suite:"RayTrace"},
53    {name:"regexp",        files:["regexp.js"],                        suite:"RegExpSuite"},
54    {name:"richards",      files:["richards.js"],                      suite:"Richards"},
55    {name:"splay",         files:["splay.js"],                         suite:"Splay"},
56    {name:"typescript",    files:["typescript.js", "typescript-input.js", "typescript-compiler.js"], suite:"typescript"},
57    //zlib currently disabled - requires read
58    {name:"zlib",          files:["zlib.js", "zlib-data.js"], suite:"zlib", before:initZlib}
59];
60var dir = (typeof(__DIR__) == 'undefined') ? "test/script/basic/" : __DIR__;
61
62// TODO: why is this path hard coded when it's defined in project properties?
63var path = dir + "../external/octane/";
64
65var runtime = "";
66var verbose = false;
67
68var numberOfIterations = 5;
69
70function endsWith(str, suffix) {
71    return str.indexOf(suffix, str.length - suffix.length) !== -1;
72}
73
74function should_compile_only(name) {
75    return (typeof compile_only !== 'undefined')
76}
77
78function load_bench(arg) {
79
80    for (var idx = 0; idx < arg.files.length; idx++) {
81	var f = arg.files[idx];
82	var file = f.split('/');
83	var file_name = path + file[file.length - 1];
84
85	var compile_and_return = should_compile_only(file_name);
86	if (compile_and_return) {
87	    if (typeof compile_only === 'undefined') { //for a run, skip compile onlies, don't even compile them
88		return true;
89	    }
90	}
91
92	print_verbose(arg, "loading '" + arg.name + "' [" + f + "]...");
93	load(file_name);
94    }
95
96    if (typeof arg.before !== 'undefined') {
97	arg.before();
98    }
99
100    if (compile_and_return) {
101	print_always(arg, "Compiled OK");
102    }
103    return !compile_and_return;
104
105}
106
107
108function run_one_benchmark(arg, iters) {
109
110    if (!load_bench(arg)) {
111	return;
112    }
113
114    var success = true;
115    var current_name;
116
117    if (iters == undefined) {
118	iters = numberOfIterations;
119    } else {
120	numberOfIterations = iters;
121    }
122
123    var benchmarks = eval(arg.suite + ".benchmarks");
124    var min_score  = 1e9;
125    var max_score  = 0;
126    var mean_score = 0;
127
128    try {
129	for (var x = 0; x < benchmarks.length ; x++) {
130	    //do warmup run
131	    //reset random number generator needed as of octane 9 before each run
132	    BenchmarkSuite.ResetRNG();
133	    benchmarks[x].Setup();
134	}
135	BenchmarkSuite.ResetRNG();
136	print_verbose(arg, "running '" + arg.name + "' for " + iters + " iterations of no less than " + min_time + " seconds (" + runtime + ")");
137
138	var scores = [];
139
140	var min_time_ms = min_time * 1000;
141	var len = benchmarks.length;
142
143	for (var it = 0; it < iters + 1; it++) {
144	    //every iteration must take a minimum of 10 secs
145	    var ops = 0;
146	    var elapsed = 0;
147	    var start = new Date;
148	    do {
149		for (var i = 0; i < len; i++) {
150		    benchmarks[i].run();
151		    //important - no timing here like elapsed = new Date() - start, as in the
152		    //original harness. This will make timing very non-deterministic.
153		    //NOTHING else must live in this loop
154		}
155		ops += len;
156		elapsed = new Date - start;
157	    } while (elapsed < min_time * 1000);
158
159	    var score = ops / elapsed * 1000 * 60;
160	    scores.push(score);
161	    var name = it == 0 ? "warmup" : "iteration " + it;
162	    print_verbose(arg, name + " finished " + score.toFixed(0) + " ops/minute");
163	}
164
165	for (var x = 0; x < benchmarks.length ; x++) {
166	    benchmarks[x].TearDown();
167	}
168
169	for (var x = 1; x < iters + 1 ; x++) {
170	    mean_score += scores[x];
171	    min_score = Math.min(min_score, scores[x]);
172	    max_score = Math.max(max_score, scores[x]);
173	}
174	mean_score /= iters;
175
176    } catch (e) {
177	print_always("*** Aborted and setting score to zero. Reason: " + e);
178	if (e instanceof java.lang.Throwable) {
179	    e.printStackTrace();
180	}
181	mean_score = min_score = max_score = 0;
182	scores = [0];
183    }
184
185    var res = mean_score.toFixed(0);
186    if (verbose) {
187	res += " ops/minute (" + min_score.toFixed(0) + "-" + max_score.toFixed(0) + "), warmup=" + scores[0].toFixed(0);
188    }
189    print_always(arg, res);
190}
191
192function print_always(arg, x) {
193    print("[" + arg.name + "] " + x);
194}
195
196function print_verbose(arg, x) {
197    if (verbose) {
198	print_always(arg, x)
199    }
200}
201
202function run_suite(tests, iters) {
203    for (var idx = 0; idx < tests.length; idx++) {
204	run_one_benchmark(tests[idx], iters);
205    }
206}
207
208runtime = "command line";
209
210var args = [];
211
212if (typeof $ARGS !== 'undefined') {
213    args = $ARGS;
214} else if (typeof arguments !== 'undefined' && arguments.length != 0) {
215    args = arguments;
216}
217
218var new_args = [];
219for (i in args) {
220    if (args[i].toString().indexOf(' ') != -1) {
221	args[i] = args[i].replace(/\/$/, '');
222	var s = args[i].split(' ');
223	for (j in s) {
224	    new_args.push(s[j]);
225	}
226    } else {
227	new_args.push(args[i]);
228    }
229}
230
231if (new_args.length != 0) {
232    args = new_args;
233}
234
235var tests_found = [];
236var iters = undefined;
237var min_time = 5;
238
239for (var i = 0; i < args.length; i++) {
240    arg = args[i];
241    if (arg == "--iterations") {
242	iters = +args[++i];
243	if (isNaN(iters)) {
244	    throw "'--iterations' must be followed by integer";
245	}
246    } else if (arg == "--runtime") {
247	runtime = args[++i];
248    } else if (arg == "--verbose") {
249	verbose = true;
250    } else if (arg == "--min-time") {
251	min_time = +args[++i];
252	if (isNaN(iters)) {
253	    throw "'--min-time' must be followed by integer";
254	}
255    } else if (arg == "") {
256	continue; //skip
257    } else {
258	var found = false;
259	for (j in tests) {
260	    if (tests[j].name === arg) {
261		tests_found.push(tests[j]);
262		found = true;
263		break;
264	    }
265	}
266	if (!found) {
267	    var str = "unknown test name: '" + arg + "' -- valid names are: ";
268	    for (j in tests) {
269		if (j != 0) {
270		    str += ", ";
271		}
272		str += "'" + tests[j].name + "'";
273	    }
274	    throw str;
275	}
276    }
277}
278
279if (tests_found.length == 0) {
280    for (i in tests) {
281	tests_found.push(tests[i]);
282    }
283}
284
285tests_found.sort();
286
287load(path + 'base.js');
288run_suite(tests_found, iters);
289
290
291
292