@@ -40,17 +40,21 @@ globalThis.dumpJSONResults ??= false;
40
40
globalThis . testList ??= undefined ;
41
41
globalThis . startDelay ??= undefined ;
42
42
globalThis . shouldReport ??= false ;
43
+ globalThis . prefetchResources ??= true ;
43
44
44
45
function getIntParam ( urlParams , key ) {
45
- if ( ! urlParams . has ( key ) )
46
- return undefined
47
46
const rawValue = urlParams . get ( key ) ;
48
47
const value = parseInt ( rawValue ) ;
49
48
if ( value <= 0 )
50
49
throw new Error ( `Expected positive value for ${ key } , but got ${ rawValue } ` ) ;
51
50
return value ;
52
51
}
53
52
53
+ function getBoolParam ( urlParams , key ) {
54
+ const rawValue = urlParams . get ( key ) . toLowerCase ( )
55
+ return ! ( rawValue === "false" || rawValue === "0" )
56
+ }
57
+
54
58
function getTestListParam ( urlParams , key ) {
55
59
if ( globalThis . testList ?. length )
56
60
throw new Error ( `Overriding previous testList=${ globalThis . testList . join ( ) } with ${ key } url-parameter.` ) ;
@@ -73,8 +77,13 @@ if (typeof(URLSearchParams) !== "undefined") {
73
77
globalThis . testIterationCount = getIntParam ( urlParameters , "iterationCount" ) ;
74
78
if ( urlParameters . has ( "worstCaseCount" ) )
75
79
globalThis . testWorstCaseCount = getIntParam ( urlParameters , "worstCaseCount" ) ;
80
+ if ( urlParameters . has ( "prefetchResources" ) )
81
+ globalThis . prefetchResources = getBoolParam ( urlParameters , "prefetchResources" ) ;
76
82
}
77
83
84
+ if ( ! globalThis . prefetchResources )
85
+ console . warn ( "Disabling resource prefetching!" ) ;
86
+
78
87
// Used for the promise representing the current benchmark run.
79
88
this . currentResolve = null ;
80
89
this . currentReject = null ;
@@ -88,7 +97,7 @@ function displayCategoryScores() {
88
97
89
98
let summaryElement = document . getElementById ( "result-summary" ) ;
90
99
for ( let [ category , scores ] of categoryScores )
91
- summaryElement . innerHTML += `<p> ${ category } : ${ uiFriendlyScore ( geomean ( scores ) ) } </p>`
100
+ summaryElement . innerHTML += `<p> ${ category } : ${ uiFriendlyScore ( geomeanScore ( scores ) ) } </p>`
92
101
93
102
categoryScores = null ;
94
103
}
@@ -138,12 +147,15 @@ function mean(values) {
138
147
return sum / values . length ;
139
148
}
140
149
141
- function geomean ( values ) {
150
+ function geomeanScore ( values ) {
142
151
assert ( values instanceof Array ) ;
143
152
let product = 1 ;
144
153
for ( let x of values )
145
154
product *= x ;
146
- return product ** ( 1 / values . length ) ;
155
+ const score = product ** ( 1 / values . length ) ;
156
+ // Allow 0 for uninitialized subScores().
157
+ assert ( score >= 0 , `Got invalid score: ${ score } ` )
158
+ return score ;
147
159
}
148
160
149
161
function toScore ( timeValue ) {
@@ -180,28 +192,29 @@ function uiFriendlyDuration(time) {
180
192
// TODO: Cleanup / remove / merge. This is only used for caching loads in the
181
193
// non-browser setting. In the browser we use exclusively `loadCache`,
182
194
// `loadBlob`, `doLoadBlob`, `prefetchResourcesForBrowser` etc., see below.
183
- const fileLoader = ( function ( ) {
184
- class Loader {
185
- constructor ( ) {
186
- this . requests = new Map ;
187
- }
188
-
189
- // Cache / memoize previously read files, because some workloads
190
- // share common code.
191
- load ( url ) {
192
- assert ( ! isInBrowser ) ;
195
+ class ShellFileLoader {
196
+ constructor ( ) {
197
+ this . requests = new Map ;
198
+ }
193
199
194
- if ( this . requests . has ( url ) ) {
195
- return this . requests . get ( url ) ;
196
- }
200
+ // Cache / memoize previously read files, because some workloads
201
+ // share common code.
202
+ load ( url ) {
203
+ assert ( ! isInBrowser ) ;
204
+ if ( ! globalThis . prefetchResources )
205
+ return `load("${ url } ");`
197
206
198
- const contents = readFile ( url ) ;
199
- this . requests . set ( url , contents ) ;
200
- return contents ;
207
+ if ( this . requests . has ( url ) ) {
208
+ return this . requests . get ( url ) ;
201
209
}
210
+
211
+ const contents = readFile ( url ) ;
212
+ this . requests . set ( url , contents ) ;
213
+ return contents ;
202
214
}
203
- return new Loader ;
204
- } ) ( ) ;
215
+ } ;
216
+
217
+ const shellFileLoader = new ShellFileLoader ( ) ;
205
218
206
219
class Driver {
207
220
constructor ( benchmarks ) {
@@ -211,6 +224,7 @@ class Driver {
211
224
// Make benchmark list unique and sort it.
212
225
this . benchmarks = Array . from ( new Set ( benchmarks ) ) ;
213
226
this . benchmarks . sort ( ( a , b ) => a . plan . name . toLowerCase ( ) < b . plan . name . toLowerCase ( ) ? 1 : - 1 ) ;
227
+ assert ( this . benchmarks . length , "No benchmarks selected" ) ;
214
228
// TODO: Cleanup / remove / merge `blobDataCache` and `loadCache` vs.
215
229
// the global `fileLoader` cache.
216
230
this . blobDataCache = { } ;
@@ -248,7 +262,7 @@ class Driver {
248
262
performance . mark ( "update-ui" ) ;
249
263
benchmark . updateUIAfterRun ( ) ;
250
264
251
- if ( isInBrowser ) {
265
+ if ( isInBrowser && globalThis . prefetchResources ) {
252
266
const cache = JetStream . blobDataCache ;
253
267
for ( const file of benchmark . plan . files ) {
254
268
const blobData = cache [ file ] ;
@@ -270,8 +284,11 @@ class Driver {
270
284
}
271
285
272
286
const allScores = [ ] ;
273
- for ( const benchmark of this . benchmarks )
274
- allScores . push ( benchmark . score ) ;
287
+ for ( const benchmark of this . benchmarks ) {
288
+ const score = benchmark . score ;
289
+ assert ( score > 0 , `Invalid ${ benchmark . name } score: ${ score } ` ) ;
290
+ allScores . push ( score ) ;
291
+ }
275
292
276
293
categoryScores = new Map ;
277
294
for ( const benchmark of this . benchmarks ) {
@@ -282,23 +299,27 @@ class Driver {
282
299
for ( const benchmark of this . benchmarks ) {
283
300
for ( let [ category , value ] of Object . entries ( benchmark . subScores ( ) ) ) {
284
301
const arr = categoryScores . get ( category ) ;
302
+ assert ( value > 0 , `Invalid ${ benchmark . name } ${ category } score: ${ value } ` ) ;
285
303
arr . push ( value ) ;
286
304
}
287
305
}
288
306
307
+ const totalScore = geomeanScore ( allScores ) ;
308
+ assert ( totalScore > 0 , `Invalid total score: ${ totalScore } ` ) ;
309
+
289
310
if ( isInBrowser ) {
290
- summaryElement . classList . add ( ' done' ) ;
291
- summaryElement . innerHTML = `<div class="score">${ uiFriendlyScore ( geomean ( allScores ) ) } </div><label>Score</label>` ;
311
+ summaryElement . classList . add ( " done" ) ;
312
+ summaryElement . innerHTML = `<div class="score">${ uiFriendlyScore ( totalScore ) } </div><label>Score</label>` ;
292
313
summaryElement . onclick = displayCategoryScores ;
293
314
if ( showScoreDetails )
294
315
displayCategoryScores ( ) ;
295
- statusElement . innerHTML = '' ;
316
+ statusElement . innerHTML = "" ;
296
317
} else if ( ! dumpJSONResults ) {
297
318
console . log ( "\n" ) ;
298
319
for ( let [ category , scores ] of categoryScores )
299
- console . log ( `${ category } : ${ uiFriendlyScore ( geomean ( scores ) ) } ` ) ;
320
+ console . log ( `${ category } : ${ uiFriendlyScore ( geomeanScore ( scores ) ) } ` ) ;
300
321
301
- console . log ( "\nTotal Score: " , uiFriendlyScore ( geomean ( allScores ) ) , "\n" ) ;
322
+ console . log ( "\nTotal Score: " , uiFriendlyScore ( totalScore ) , "\n" ) ;
302
323
}
303
324
304
325
this . reportScoreToRunBenchmarkRunner ( ) ;
@@ -727,7 +748,7 @@ class Benchmark {
727
748
728
749
get score ( ) {
729
750
const subScores = Object . values ( this . subScores ( ) ) ;
730
- return geomean ( subScores ) ;
751
+ return geomeanScore ( subScores ) ;
731
752
}
732
753
733
754
subScores ( ) {
@@ -788,8 +809,9 @@ class Benchmark {
788
809
scripts . add ( text ) ;
789
810
} else {
790
811
const cache = JetStream . blobDataCache ;
791
- for ( const file of this . plan . files )
792
- scripts . addWithURL ( cache [ file ] . blobURL ) ;
812
+ for ( const file of this . plan . files ) {
813
+ scripts . addWithURL ( globalThis . prefetchResources ? cache [ file ] . blobURL : file ) ;
814
+ }
793
815
}
794
816
795
817
const promise = new Promise ( ( resolve , reject ) => {
@@ -838,6 +860,11 @@ class Benchmark {
838
860
}
839
861
840
862
async doLoadBlob ( resource ) {
863
+ const blobData = JetStream . blobDataCache [ resource ] ;
864
+ if ( ! globalThis . prefetchResources ) {
865
+ blobData . blobURL = resource ;
866
+ return blobData ;
867
+ }
841
868
let response ;
842
869
let tries = 3 ;
843
870
while ( tries -- ) {
@@ -854,7 +881,6 @@ class Benchmark {
854
881
throw new Error ( "Fetch failed" ) ;
855
882
}
856
883
const blob = await response . blob ( ) ;
857
- const blobData = JetStream . blobDataCache [ resource ] ;
858
884
blobData . blob = blob ;
859
885
blobData . blobURL = URL . createObjectURL ( blob ) ;
860
886
return blobData ;
@@ -987,7 +1013,7 @@ class Benchmark {
987
1013
assert ( ! isInBrowser ) ;
988
1014
989
1015
assert ( this . scripts === null , "This initialization should be called only once." ) ;
990
- this . scripts = this . plan . files . map ( file => fileLoader . load ( file ) ) ;
1016
+ this . scripts = this . plan . files . map ( file => shellFileLoader . load ( file ) ) ;
991
1017
992
1018
assert ( this . preloads === null , "This initialization should be called only once." ) ;
993
1019
this . preloads = Object . entries ( this . plan . preload ?? { } ) ;
@@ -2417,8 +2443,7 @@ for (const benchmark of BENCHMARKS) {
2417
2443
}
2418
2444
2419
2445
2420
- function processTestList ( testList )
2421
- {
2446
+ function processTestList ( testList ) {
2422
2447
let benchmarkNames = [ ] ;
2423
2448
let benchmarks = [ ] ;
2424
2449
@@ -2430,7 +2455,7 @@ function processTestList(testList)
2430
2455
for ( let name of benchmarkNames ) {
2431
2456
name = name . toLowerCase ( ) ;
2432
2457
if ( benchmarksByTag . has ( name ) )
2433
- benchmarks . concat ( findBenchmarksByTag ( name ) ) ;
2458
+ benchmarks = benchmarks . concat ( findBenchmarksByTag ( name ) ) ;
2434
2459
else
2435
2460
benchmarks . push ( findBenchmarkByName ( name ) ) ;
2436
2461
}
0 commit comments