@@ -560,20 +560,35 @@ const BenchmarkState = Object.freeze({
560560
561561
562562class Scripts {
563- constructor ( ) {
563+ constructor ( preloads ) {
564564 this . scripts = [ ] ;
565+
566+ let preloadsCode = "" ;
567+ let resourcesCode = "" ;
568+ for ( let { name, resource, blobURLOrPath } of preloads ) {
569+ console . assert ( name ?. length > 0 , "Invalid preload name." ) ;
570+ console . assert ( resource ?. length > 0 , "Invalid preload resource." ) ;
571+ console . assert ( blobURLOrPath ?. length > 0 , "Invalid preload data." ) ;
572+ preloadsCode += `${ JSON . stringify ( name ) } : "${ blobURLOrPath } ",\n` ;
573+ resourcesCode += `${ JSON . stringify ( resource ) } : "${ blobURLOrPath } ",\n` ;
574+ }
565575 // Expose a globalThis.JetStream object to the workload. We use
566576 // a proxy to prevent prototype access and throw on unknown properties.
567577 this . add ( `
568578 const throwOnAccess = (name) => new Proxy({}, {
569579 get(target, property, receiver) {
570580 throw new Error(name + "." + property + " is not defined.");
571581 }
572- });
582+ });
573583 globalThis.JetStream = {
574584 __proto__: throwOnAccess("JetStream"),
575585 preload: {
576586 __proto__: throwOnAccess("JetStream.preload"),
587+ ${ preloadsCode }
588+ },
589+ resources: {
590+ __proto__: throwOnAccess("JetStream.preload"),
591+ ${ resourcesCode }
577592 },
578593 };
579594 ` ) ;
@@ -631,8 +646,8 @@ class Scripts {
631646}
632647
633648class ShellScripts extends Scripts {
634- constructor ( ) {
635- super ( ) ;
649+ constructor ( preloads ) {
650+ super ( preloads ) ;
636651 this . prefetchedResources = Object . create ( null ) ; ;
637652 }
638653
@@ -698,8 +713,8 @@ class ShellScripts extends Scripts {
698713}
699714
700715class BrowserScripts extends Scripts {
701- constructor ( ) {
702- super ( ) ;
716+ constructor ( preloads ) {
717+ super ( preloads ) ;
703718 this . add ( "window.onerror = top.currentReject;" ) ;
704719 }
705720
@@ -738,7 +753,7 @@ class Benchmark {
738753 this . isAsync = ! ! plan . isAsync ;
739754 this . allowUtf16 = ! ! plan . allowUtf16 ;
740755 this . scripts = null ;
741- this . preloads = null ;
756+ this . preloads = [ ] ;
742757 this . shellPrefetchedResources = null ;
743758 this . results = [ ] ;
744759 this . _state = BenchmarkState . READY ;
@@ -842,8 +857,9 @@ class Benchmark {
842857
843858 get prerunCode ( ) { return null ; }
844859
860+
845861 get preIterationCode ( ) {
846- let code = `benchmark.prepareForNextIteration?.();` ;
862+ let code = this . prepareForNextIterationCode ;
847863 if ( this . plan . deterministicRandom )
848864 code += `Math.random.__resetSeed();` ;
849865
@@ -853,6 +869,10 @@ class Benchmark {
853869 return code ;
854870 }
855871
872+ get prepareForNextIterationCode ( ) {
873+ return "benchmark.prepareForNextIteration?.();"
874+ }
875+
856876 get postIterationCode ( ) {
857877 let code = "" ;
858878
@@ -893,7 +913,7 @@ class Benchmark {
893913 if ( this . isDone )
894914 throw new Error ( `Cannot run Benchmark ${ this . name } twice` ) ;
895915 this . _state = BenchmarkState . PREPARE ;
896- const scripts = isInBrowser ? new BrowserScripts ( ) : new ShellScripts ( ) ;
916+ const scripts = isInBrowser ? new BrowserScripts ( this . preloads ) : new ShellScripts ( this . preloads ) ;
897917
898918 if ( ! ! this . plan . deterministicRandom )
899919 scripts . addDeterministicRandom ( )
@@ -903,15 +923,6 @@ class Benchmark {
903923 if ( this . shellPrefetchedResources ) {
904924 scripts . addPrefetchedResources ( this . shellPrefetchedResources ) ;
905925 }
906- if ( this . plan . preload ) {
907- let preloadCode = "" ;
908- for ( let [ variableName , blobURLOrPath ] of this . preloads ) {
909- console . assert ( variableName ?. length > 0 , "Invalid preload name." ) ;
910- console . assert ( blobURLOrPath ?. length > 0 , "Invalid preload data." ) ;
911- preloadCode += `JetStream.preload[${ JSON . stringify ( variableName ) } ] = "${ blobURLOrPath } ";\n` ;
912- }
913- scripts . add ( preloadCode ) ;
914- }
915926
916927 const prerunCode = this . prerunCode ;
917928 if ( prerunCode )
@@ -1062,12 +1073,11 @@ class Benchmark {
10621073 } ) ) ;
10631074
10641075 if ( this . plan . preload ) {
1065- this . preloads = [ ] ;
10661076 for ( const [ name , resource ] of Object . entries ( this . plan . preload ) ) {
10671077 promises . push ( this . loadBlob ( "preload" , name , resource ) . then ( ( blobData ) => {
10681078 if ( ! globalThis . allIsGood )
10691079 return ;
1070- this . preloads . push ( [ blobData . prop , blobData . blobURL ] ) ;
1080+ this . preloads . push ( { name : blobData . prop , resource : blobData . resource , blobURLOrPath : blobData . blobURL } ) ;
10711081 this . updateCounter ( ) ;
10721082 } ) . catch ( ( error ) => {
10731083 // We'll try again later in retryPrefetchResourceForBrowser(). Don't throw an error.
@@ -1094,7 +1104,7 @@ class Benchmark {
10941104 if ( type == "preload" ) {
10951105 if ( this . failedPreloads && this . failedPreloads [ blobData . prop ] ) {
10961106 this . failedPreloads [ blobData . prop ] = false ;
1097- this . preloads . push ( [ blobData . prop , blobData . blobURL ] ) ;
1107+ this . preloads . push ( { name : blobData . prop , resource : blobData . resource , blobURLOrPath : blobData . blobURL } ) ;
10981108 counter . failedPreloadResources -- ;
10991109 }
11001110 }
@@ -1107,7 +1117,7 @@ class Benchmark {
11071117 if ( ! globalThis . allIsGood )
11081118 return ;
11091119 if ( blobData . type == "preload" )
1110- this . preloads . push ( [ blobData . prop , blobData . blobURL ] ) ;
1120+ this . preloads . push ( { name : blobData . prop , resource : blobData . resource , blobURLOrPath : blobData . blobURL } ) ;
11111121 this . updateCounter ( ) ;
11121122 } ) ;
11131123
@@ -1145,8 +1155,7 @@ class Benchmark {
11451155 console . assert ( this . scripts === null , "This initialization should be called only once." ) ;
11461156 this . scripts = this . plan . files . map ( file => shellFileLoader . load ( file ) ) ;
11471157
1148- console . assert ( this . preloads === null , "This initialization should be called only once." ) ;
1149- this . preloads = [ ] ;
1158+ console . assert ( this . preloads . length === 0 , "This initialization should be called only once." ) ;
11501159 this . shellPrefetchedResources = Object . create ( null ) ;
11511160 if ( ! this . plan . preload ) {
11521161 return ;
@@ -1165,7 +1174,7 @@ class Benchmark {
11651174 this . shellPrefetchedResources [ resource ] = bytes ;
11661175 }
11671176
1168- this . preloads . push ( [ name , resource ] ) ;
1177+ this . preloads . push ( { name, resource, blobURLOrPath : resource } ) ;
11691178 }
11701179 }
11711180
@@ -1519,6 +1528,10 @@ class AsyncBenchmark extends DefaultBenchmark {
15191528 return str ;
15201529 }
15211530
1531+ get prepareForNextIterationCode ( ) {
1532+ return "await benchmark.prepareForNextIteration?.();"
1533+ }
1534+
15221535 get runnerCode ( ) {
15231536 return `
15241537 async function doRun() {
@@ -2510,8 +2523,8 @@ let BENCHMARKS = [
25102523 inputFontItalic : "./Kotlin-compose/build/jetbrainsmono_italic.ttf" ,
25112524 inputFontRegular : "./Kotlin-compose/build/jetbrainsmono_regular.ttf"
25122525 } ,
2513- iterations : 15 ,
2514- worstCaseCount : 2 ,
2526+ iterations : 5 ,
2527+ worstCaseCount : 1 ,
25152528 tags : [ "default" , "Wasm" ] ,
25162529 } ) ,
25172530 new AsyncBenchmark ( {
0 commit comments