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