Skip to content

Commit d1534f0

Browse files
committed
Move Benchmark class to benchmark.js rather than have it as part of the generated code.
Remove some stale logging. Remove main from TSF-wasm since it's no longer used. Make the count value an argument rather than a constant in C code. This appears to make the performance characteristics similar to what it was before this refactor. Old sampling (after recompile so wasm function numbers are meaningful): Sampling rate: 1000.000000 microseconds. Total samples: 364 Top functions as <numSamples 'functionName#hash:sourceID'> 199 '<?>.wasm-function[100]#<nil>:4294967295' 34 '<?>.wasm-function[238]#<nil>:4294967295' 19 '<?>.wasm-function[208]#<nil>:4294967295' 16 '_platform_memmove#<nil>:4294967295' 12 '<?>.wasm-function[251]#<nil>:4294967295' 11 '<?>.wasm-function[232]#<nil>:4294967295' 9 '<?>.wasm-function[209]#<nil>:4294967295' 8 '<?>.wasm-function[237]#<nil>:4294967295' 7 '<?>.wasm-function[201]#<nil>:4294967295' 5 '<?>.wasm-function[250]#<nil>:4294967295' 4 '<?>.wasm-function[213]#<nil>:4294967295' 3 '<?>.wasm-function[216]#<nil>:4294967295' Sampling rate: 1000.000000 microseconds. Total samples: 364 Tier breakdown: ----------------------------------- LLInt: 0 (0.000000%) Baseline: 1 (0.274725%) DFG: 0 (0.000000%) FTL: 0 (0.000000%) js builtin: 0 (0.000000%) IPInt: 0 (0.000000%) WasmLLInt: 3 (0.824176%) BBQ: 211 (57.967033%) OMG: 116 (31.868132%) Wasm: 0 (0.000000%) Host: 0 (0.000000%) RegExp: 0 (0.000000%) C/C++: 30 (8.241758%) Unknown Frame: 3 (0.824176%) Hottest bytecodes as <numSamples 'functionName#hash:JITType:bytecodeIndex'> 33 '<?>.wasm-function[100]:BBQMode:0x2ed' 33 '<?>.wasm-function[100]:BBQMode:0x2f0' 16 '_platform_memmove#<nil>:None:<nil>' 8 '<?>.wasm-function[100]:BBQMode:0xa733' 7 '<?>.wasm-function[100]:BBQMode:0x70a2' 6 '<?>.wasm-function[100]:BBQMode:0x6f8a' 6 '<?>.wasm-function[100]:BBQMode:0x6f94' 5 '<?>.wasm-function[208]:OMGMode:nil' 5 '<?>.wasm-function[100]:BBQMode:0x5b' 5 '<?>.wasm-function[100]:BBQMode:0x6f9b' 4 '<?>.wasm-function[100]:BBQMode:0x5df3' ... New sampling with this PR: Sampling rate: 1000.000000 microseconds. Total samples: 4908 Top functions as <numSamples 'functionName#hash:sourceID'> 2763 '<?>.wasm-function[100]#<nil>:4294967295' 464 '<?>.wasm-function[238]#<nil>:4294967295' 436 '<?>.wasm-function[208]#<nil>:4294967295' 138 '<?>.wasm-function[251]#<nil>:4294967295' 128 '<?>.wasm-function[237]#<nil>:4294967295' 117 '<?>.wasm-function[232]#<nil>:4294967295' 108 '<?>.wasm-function[250]#<nil>:4294967295' 107 '<?>.wasm-function[209]#<nil>:4294967295' 104 '<?>.wasm-function[201]#<nil>:4294967295' 77 '<?>.wasm-function[216]#<nil>:4294967295' 54 '<?>.wasm-function[226]#<nil>:4294967295' 43 '<?>.wasm-function[162]#<nil>:4294967295' Sampling rate: 1000.000000 microseconds. Total samples: 4908 Tier breakdown: ----------------------------------- LLInt: 0 (0.000000%) Baseline: 2 (0.040750%) DFG: 2 (0.040750%) FTL: 5 (0.101874%) js builtin: 1 (0.020375%) IPInt: 0 (0.000000%) WasmLLInt: 3 (0.061125%) BBQ: 2771 (56.458843%) OMG: 1988 (40.505297%) Wasm: 0 (0.000000%) Host: 0 (0.000000%) RegExp: 0 (0.000000%) C/C++: 95 (1.935615%) Unknown Frame: 41 (0.835371%) Unknown Executable: 1 (0.020375%) Hottest bytecodes as <numSamples 'functionName#hash:JITType:bytecodeIndex'> 526 '<?>.wasm-function[100]:BBQMode:0x2ed' 451 '<?>.wasm-function[100]:BBQMode:0x2f0' 125 '<?>.wasm-function[208]:OMGMode:0x0' 105 '<?>.wasm-function[100]:BBQMode:0x6f8a' 91 '<?>.wasm-function[100]:BBQMode:0xa724' 84 '<?>.wasm-function[100]:BBQMode:0x5b' 81 '<?>.wasm-function[100]:BBQMode:0xa733' 79 '<?>.wasm-function[100]:BBQMode:0x6f94' 77 '<?>.wasm-function[100]:BBQMode:nil' 63 '<?>.wasm-function[208]:OMGMode:0x16d' ... It looks like versions have similar sample rates for the top function. There's more samples in the top tier compiler but that's presumably ok and expected as the test runs longer.
1 parent 41611c7 commit d1534f0

7 files changed

+102
-187
lines changed

JetStreamDriver.js

+6-17
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ function uiFriendlyDuration(time)
164164
const minutes = time.getMinutes();
165165
const seconds = time.getSeconds();
166166
const milliSeconds = time.getMilliseconds();
167-
const result = "" + minutes + ":";
167+
let result = "" + minutes + ":";
168168

169169
result = result + (seconds < 10 ? "0" : "") + seconds + ".";
170170
result = result + (milliSeconds < 10 ? "00" : (milliSeconds < 100 ? "0" : "")) + milliSeconds;
@@ -997,7 +997,6 @@ class AsyncBenchmark extends DefaultBenchmark {
997997
await __benchmark.runIteration();
998998
let end = performance.now();
999999
${this.postIterationCode}
1000-
console.log("iteration i: " + (end - start));
10011000
results.push(Math.max(1, end - start));
10021001
}
10031002
if (__benchmark.validate)
@@ -1008,9 +1007,8 @@ class AsyncBenchmark extends DefaultBenchmark {
10081007
}
10091008
};
10101009

1011-
// Meant for wasm benchmarks that are directly compiled with an emcc script and not part of a larger project's build system.
1012-
// Requires the following flags to emcc `-s MODULARIZE=1 -s EXPORT_NAME=setupModule -s EXPORTED_FUNCTIONS=_runIteration`
1013-
// in addition to any other benchmark specific flags.
1010+
// Meant for wasm benchmarks that are directly compiled with an emcc build script. It might not work for benchmarks built as
1011+
// part of a larger project's build system or a wasm benchmark compiled from a language that doesn't compile with emcc.
10141012
class WasmEMCCBenchmark extends AsyncBenchmark {
10151013
get prerunCode() {
10161014
let str = `
@@ -1084,18 +1082,8 @@ class WasmEMCCBenchmark extends AsyncBenchmark {
10841082

10851083
let keys = Object.keys(this.plan.preload);
10861084
for (let i = 0; i < keys.length; ++i) {
1087-
str += `loadBlob("${keys[i]}", "${this.plan.preload[keys[i]]}", () => {\n`;
1085+
str += `loadBlob("${keys[i]}", "${this.plan.preload[keys[i]]}", async () => {\n`;
10881086
}
1089-
str += `
1090-
class Benchmark {
1091-
async runIteration() {
1092-
if (!Module["_runIteration"])
1093-
await setupModule(Module);
1094-
1095-
Module["_runIteration"]();
1096-
}
1097-
};
1098-
`
10991087

11001088
str += super.runnerCode;
11011089
for (let i = 0; i < keys.length; ++i) {
@@ -1902,7 +1890,8 @@ const testPlans = [
19021890
{
19031891
name: "tsf-wasm",
19041892
files: [
1905-
"./wasm/TSF/tsf.js"
1893+
"./wasm/TSF/tsf.js",
1894+
"./wasm/TSF/benchmark.js",
19061895
],
19071896
preload: {
19081897
wasmBinary: "./wasm/TSF/tsf.wasm"

wasm/TSF/benchmark.js

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright (C) 2024 Apple Inc. All rights reserved.
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions
6+
* are met:
7+
* 1. Redistributions of source code must retain the above copyright
8+
* notice, this list of conditions and the following disclaimer.
9+
* 2. Redistributions in binary form must reproduce the above copyright
10+
* notice, this list of conditions and the following disclaimer in the
11+
* documentation and/or other materials provided with the distribution.
12+
*
13+
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15+
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17+
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23+
* THE POSSIBILITY OF SUCH DAMAGE.
24+
*/
25+
26+
class Benchmark {
27+
async runIteration() {
28+
if (!Module._runIteration)
29+
await setupModule(Module);
30+
31+
Module._runIteration(150);
32+
}
33+
};

wasm/TSF/build.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
set -euo pipefail
44

55
emcc \
6-
-o tsf.js -O2 -s MODULARIZE=1 -s EXPORT_NAME=setupModule -s WASM=1 -s TOTAL_MEMORY=52428800 -g1 --emit-symbol-map -s EXPORTED_FUNCTIONS=_main,_runIteration \
6+
-o tsf.js -O2 -s MODULARIZE=1 -s EXPORT_NAME=setupModule -s WASM=1 -s TOTAL_MEMORY=52428800 -g1 --emit-symbol-map -s EXPORTED_FUNCTIONS=_runIteration \
77
-I. -DTSF_BUILD_SYSTEM=1 \
88
tsf_asprintf.c\
99
tsf_buffer.c\

wasm/TSF/tsf.js

+2-62
Original file line numberDiff line numberDiff line change
@@ -250,9 +250,6 @@ var __ATPRERUN__ = [];
250250
// functions called before the runtime is initialized
251251
var __ATINIT__ = [];
252252

253-
// functions called during startup
254-
var __ATMAIN__ = [];
255-
256253
// functions called during shutdown
257254
var __ATPOSTRUN__ = [];
258255

@@ -277,10 +274,6 @@ function initRuntime() {
277274
callRuntimeCallbacks(__ATINIT__);
278275
}
279276

280-
function preMain() {
281-
callRuntimeCallbacks(__ATMAIN__);
282-
}
283-
284277
function postRun() {
285278
if (Module["postRun"]) {
286279
if (typeof Module["postRun"] == "function") Module["postRun"] = [ Module["postRun"] ];
@@ -3505,29 +3498,6 @@ function _fd_write(fd, iov, iovcnt, pnum) {
35053498
}
35063499
}
35073500

3508-
var handleException = e => {
3509-
// Certain exception types we do not treat as errors since they are used for
3510-
// internal control flow.
3511-
// 1. ExitStatus, which is thrown by exit()
3512-
// 2. "unwind", which is thrown by emscripten_unwind_to_js_event_loop() and others
3513-
// that wish to return to JS event loop.
3514-
if (e instanceof ExitStatus || e == "unwind") {
3515-
return EXITSTATUS;
3516-
}
3517-
quit_(1, e);
3518-
};
3519-
3520-
var stringToUTF8 = (str, outPtr, maxBytesToWrite) => stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
3521-
3522-
var stackAlloc = sz => __emscripten_stack_alloc(sz);
3523-
3524-
var stringToUTF8OnStack = str => {
3525-
var size = lengthBytesUTF8(str) + 1;
3526-
var ret = stackAlloc(size);
3527-
stringToUTF8(str, ret, size);
3528-
return ret;
3529-
};
3530-
35313501
FS.createPreloadedFile = FS_createPreloadedFile;
35323502

35333503
FS.staticInit();
@@ -3560,9 +3530,7 @@ var wasmExports = createWasm();
35603530

35613531
var ___wasm_call_ctors = () => (___wasm_call_ctors = wasmExports["__wasm_call_ctors"])();
35623532

3563-
var _main = Module["_main"] = (a0, a1) => (_main = Module["_main"] = wasmExports["__main_argc_argv"])(a0, a1);
3564-
3565-
var _runIteration = Module["_runIteration"] = () => (_runIteration = Module["_runIteration"] = wasmExports["runIteration"])();
3533+
var _runIteration = Module["_runIteration"] = a0 => (_runIteration = Module["_runIteration"] = wasmExports["runIteration"])(a0);
35663534

35673535
var __emscripten_stack_restore = a0 => (__emscripten_stack_restore = wasmExports["_emscripten_stack_restore"])(a0);
35683536

@@ -3583,28 +3551,7 @@ dependenciesFulfilled = function runCaller() {
35833551
};
35843552

35853553
// try this again later, after new deps are fulfilled
3586-
function callMain(args = []) {
3587-
var entryFunction = _main;
3588-
args.unshift(thisProgram);
3589-
var argc = args.length;
3590-
var argv = stackAlloc((argc + 1) * 4);
3591-
var argv_ptr = argv;
3592-
args.forEach(arg => {
3593-
HEAPU32[((argv_ptr) >> 2)] = stringToUTF8OnStack(arg);
3594-
argv_ptr += 4;
3595-
});
3596-
HEAPU32[((argv_ptr) >> 2)] = 0;
3597-
try {
3598-
var ret = entryFunction(argc, argv);
3599-
// if we're not running an evented main loop, it's time to exit
3600-
exitJS(ret, /* implicit = */ true);
3601-
return ret;
3602-
} catch (e) {
3603-
return handleException(e);
3604-
}
3605-
}
3606-
3607-
function run(args = arguments_) {
3554+
function run() {
36083555
if (runDependencies > 0) {
36093556
return;
36103557
}
@@ -3621,10 +3568,8 @@ function run(args = arguments_) {
36213568
Module["calledRun"] = true;
36223569
if (ABORT) return;
36233570
initRuntime();
3624-
preMain();
36253571
readyPromiseResolve(Module);
36263572
Module["onRuntimeInitialized"]?.();
3627-
if (shouldRunNow) callMain(args);
36283573
postRun();
36293574
}
36303575
if (Module["setStatus"]) {
@@ -3645,11 +3590,6 @@ if (Module["preInit"]) {
36453590
}
36463591
}
36473592

3648-
// shouldRunNow refers to calling main(), not run().
3649-
var shouldRunNow = true;
3650-
3651-
if (Module["noInitialRun"]) shouldRunNow = false;
3652-
36533593
run();
36543594

36553595
// end include: postamble.js

wasm/TSF/tsf.js.symbols

+59-60
Original file line numberDiff line numberDiff line change
@@ -198,63 +198,62 @@
198198
197:DProcedureDefn__variables__get_type
199199
198:DProcedureDefn__code__get_type
200200
199:DProgram__globals__get_type
201-
200:main
202-
201:runIteration
203-
202:__stdio_close
204-
203:__stdio_read
205-
204:__stdio_seek
206-
205:__stdio_write
207-
206:abort
208-
207:close
209-
208:__memcpy
210-
209:__memset
211-
210:__gettimeofday
212-
211:fflush
213-
212:fiprintf
214-
213:__towrite
215-
214:__overflow
216-
215:fputc
217-
216:__fwritex
218-
217:getenv
219-
218:__bswap_32
220-
219:__lseek
221-
220:open
222-
221:__small_printf
223-
222:read
224-
223:snprintf
225-
224:__emscripten_stdout_close
226-
225:__emscripten_stdout_seek
227-
226:__stpcpy
228-
227:strchr
229-
228:__strchrnul
230-
229:strcmp
231-
230:strdup
232-
231:__strerror_l
233-
232:strlen
234-
233:__syscall_ret
235-
234:tolower
236-
235:vasprintf
237-
236:frexp
238-
237:__vfprintf_internal
239-
238:printf_core
240-
239:out
241-
240:getint
242-
241:pop_arg
243-
242:fmt_u
244-
243:pad
245-
244:fmt_fp
246-
245:pop_arg_long_double
247-
246:vsnprintf
248-
247:sn_write
249-
248:__wasi_syscall_ret
250-
249:wctomb
251-
250:emscripten_builtin_malloc
252-
251:emscripten_builtin_free
253-
252:dlrealloc
254-
253:dispose_chunk
255-
254:emscripten_builtin_calloc
256-
255:sbrk
257-
256:_emscripten_stack_restore
258-
257:_emscripten_stack_alloc
259-
258:emscripten_stack_get_current
260-
259:legalstub$dynCall_jiji
201+
200:runIteration
202+
201:__stdio_close
203+
202:__stdio_read
204+
203:__stdio_seek
205+
204:__stdio_write
206+
205:abort
207+
206:close
208+
207:__memcpy
209+
208:__memset
210+
209:__gettimeofday
211+
210:fflush
212+
211:fiprintf
213+
212:__towrite
214+
213:__overflow
215+
214:fputc
216+
215:__fwritex
217+
216:getenv
218+
217:__bswap_32
219+
218:__lseek
220+
219:open
221+
220:__small_printf
222+
221:read
223+
222:snprintf
224+
223:__emscripten_stdout_close
225+
224:__emscripten_stdout_seek
226+
225:__stpcpy
227+
226:strchr
228+
227:__strchrnul
229+
228:strcmp
230+
229:strdup
231+
230:__strerror_l
232+
231:strlen
233+
232:__syscall_ret
234+
233:tolower
235+
234:vasprintf
236+
235:frexp
237+
236:__vfprintf_internal
238+
237:printf_core
239+
238:out
240+
239:getint
241+
240:pop_arg
242+
241:fmt_u
243+
242:pad
244+
243:fmt_fp
245+
244:pop_arg_long_double
246+
245:vsnprintf
247+
246:sn_write
248+
247:__wasi_syscall_ret
249+
248:wctomb
250+
249:emscripten_builtin_malloc
251+
250:emscripten_builtin_free
252+
251:dlrealloc
253+
252:dispose_chunk
254+
253:emscripten_builtin_calloc
255+
254:sbrk
256+
255:_emscripten_stack_restore
257+
256:_emscripten_stack_alloc
258+
257:emscripten_stack_get_current
259+
258:legalstub$dynCall_jiji

wasm/TSF/tsf.wasm

-79 Bytes
Binary file not shown.

wasm/TSF/tsf_ir_speed.c

+1-47
Original file line numberDiff line numberDiff line change
@@ -321,56 +321,10 @@ static void readConvertTest(const char *filename, unsigned numPrograms) {
321321
tsf_stream_file_input_close(in);
322322
}
323323

324-
int main(int c, char **v) {
325-
// static const char *filename = "tsf_ir_speed_test_file.tsf";
326-
// static const char *zipFilename = "tsf_ir_speed_test_zip_file.tsf";
327-
328-
// unsigned count;
329-
330-
// switch (c) {
331-
// case 1:
332-
// /* Use a small problem size suitable for regression testing. */
333-
// count = 1000;
334-
// break;
335-
336-
// case 2:
337-
// if (sscanf(v[1], "%u", &count) != 1) {
338-
// usage();
339-
// }
340-
// break;
341-
342-
// default:
343-
// usage();
344-
// return 1;
345-
// }
346-
347-
// printf("Writing %u programs.\n", count);
348-
// if (count != 10000)
349-
// printf("WARNING: If you are benchmarking, please use count = 10000.\n");
350-
351-
// TIMEIT(writeTest(filename, 100, count, TSF_ZIP_NONE));
352-
// TIMEIT(readTest(filename, count));
353-
// TIMEIT(readMallocTest(filename, count));
354-
// TIMEIT(readConvertTest(filename, count));
355-
356-
// if (tsf_zlib_supported()) {
357-
// TIMEIT(writeTest(zipFilename, 100, count, TSF_ZIP_ZLIB));
358-
// TIMEIT(readTest(zipFilename, count));
359-
// TIMEIT(readMallocTest(filename, count));
360-
// TIMEIT(readConvertTest(zipFilename, count));
361-
// }
362-
363-
/* We don't benchmark bzip2 because it's just too slow to be interesting. */
364-
365-
return 0;
366-
}
367-
368-
int runIteration() {
324+
int runIteration(unsigned count) {
369325
static const char *filename = "tsf_ir_speed_test_file.tsf";
370326
static const char *zipFilename = "tsf_ir_speed_test_zip_file.tsf";
371327

372-
unsigned count = 150;
373-
374328
TIMEIT(writeTest(filename, 100, count, TSF_ZIP_NONE));
375329
TIMEIT(readTest(filename, count));
376330
TIMEIT(readMallocTest(filename, count));

0 commit comments

Comments
 (0)