diff --git a/tests/benchmark/README.md b/tests/benchmark/README.md index 57fc291b..2afc5dbf 100644 --- a/tests/benchmark/README.md +++ b/tests/benchmark/README.md @@ -39,7 +39,9 @@ These benchmarks are based on some open source efforts to measure performance of # run specific benchmark node run_benchmark.js --benchmark binarytrees # run specific runtime mode - node run_benchmark.js --runtime wamr-aot # (wamr-aot | wamr-interp | qjs) + node run_benchmark.js --runtimes wamr-aot # (wamr-aot | wamr-interp | qjs | node) + # get result after multiple times warm up + node run_benchmark.js --warmup 3 ``` ## Validate benchmark result diff --git a/tests/benchmark/run_benchmark.js b/tests/benchmark/run_benchmark.js index bb23c41c..72bdc624 100644 --- a/tests/benchmark/run_benchmark.js +++ b/tests/benchmark/run_benchmark.js @@ -54,6 +54,7 @@ const wamr_stack_size = args['--stack-size'] ? parseInt(args['--stack-size']) : const wamr_gc_heap = args['--gc-heap'] ? parseInt(args['--gc-heap']) : 40960000; const specifed_benchmarks = args['--benchmarks'] ? args['--benchmarks'].split(',') : null; const specified_runtimes = args['--runtimes'] ? args['--runtimes'].split(',') : null; +const warm_up_times = args['--warmup'] ? parseInt(args['--warmup']) : 0; const default_gc_size_option = `--gc-heap-size=${wamr_gc_heap}` const stack_size_option = `--stack-size=${wamr_stack_size}` @@ -80,9 +81,27 @@ try { } } -let ts_times = []; -let js_times = []; -let aot_times = []; +let node_cmd; +try { + node_cmd = execSync('which node').toString().trim(); +} catch (error) { + if (process.env.NODE_PATH) { + node_cmd = process.env.NODE_PATH; + } else { + const default_node_path = '/usr/local/bin/node'; + if (fs.existsSync(default_node_path)) { + node_cmd = default_node_path; + } else { + console.error("Error: NODE_PATH is not defined, and no default node path is provided."); + process.exit(1); + } + } +} + +let wamr_interp_times = []; +let qjs_js_times = []; +let wamr_aot_times = []; +let v8_js_times = []; let prefixs = []; let benchmark_options = { @@ -118,6 +137,7 @@ function collect_benchmark_options(options) { console.log(`\x1b[33m======================== options ========================\x1b[0m`); console.log(`QJS_PATH: ${qjs}`); +console.log(`NODE_PATH: ${node_cmd}`); console.log(`strategy: run ${multirun} times and get average`); console.log(`clean generated files: ${shouldClean ? 'true' : 'false'}`); console.log(`\x1b[33m======================== running ========================\x1b[0m`); @@ -127,6 +147,9 @@ function run_multiple_times(cmd) { let elapse_arr = []; try { + for (let i = 0; i < warm_up_times; i++) { + execSync(cmd); + } for (let i = 0; i < multirun; i++) { let start = performance.now(); let ret = execSync(cmd); @@ -192,7 +215,7 @@ for (let benchmark of benchmarks) { else { process.stdout.write(`WAMR interpreter ... \t`); elapsed = run_multiple_times(`${iwasm_gc} ${collect_benchmark_options(benchmark_options[prefix]?.wamr_option)} -f main ${prefix}.wasm`); - ts_times.push(elapsed); + wamr_interp_times.push(elapsed); console.log(`${elapsed.toFixed(2)}ms`); } @@ -202,7 +225,7 @@ for (let benchmark of benchmarks) { else { process.stdout.write(`WAMR AoT ... \t\t`); elapsed = run_multiple_times(`${iwasm_gc} ${collect_benchmark_options(benchmark_options[prefix]?.wamr_option)} -f main ${prefix}.aot`); - aot_times.push(elapsed); + wamr_aot_times.push(elapsed); console.log(`${elapsed.toFixed(2)}ms`); } @@ -212,7 +235,17 @@ for (let benchmark of benchmarks) { else { process.stdout.write(`QuickJS ... \t\t`); elapsed = run_multiple_times(`${qjs} ${js_file}`); - js_times.push(elapsed); + qjs_js_times.push(elapsed); + console.log(`${elapsed.toFixed(2)}ms`); + } + + if (specified_runtimes && !specified_runtimes.includes('node')) { + console.log(`\x1b[33mSkip Node due to argument filter.\x1b[0m`); + } + else { + process.stdout.write(`Node ... \t\t`); + elapsed = run_multiple_times(`${node_cmd} ${js_file}`); + v8_js_times.push(elapsed); console.log(`${elapsed.toFixed(2)}ms`); } @@ -229,38 +262,55 @@ console.log(`\x1b[32m====================== results ======================\x1b[0 let results = []; for (let i = 0; i < executed_benchmarks; i++) { - let ts_time = ts_times[i]; - let js_time = js_times[i]; - let aot_time = aot_times[i]; + let wamr_interp_time = wamr_interp_times[i]; + let qjs_js_time = qjs_js_times[i]; + let wamr_aot_time = wamr_aot_times[i]; + let v8_js_time = v8_js_times[i]; let r = { benchmark: prefixs[i] } - if (ts_time) { - r['WAMR_interpreter'] = ts_time.toFixed(2) + 'ms'; + if (wamr_interp_time) { + r['WAMR_interpreter'] = wamr_interp_time.toFixed(2) + 'ms'; } - if (aot_time) { - r['WAMR_aot'] = aot_time.toFixed(2) + 'ms'; + if (wamr_aot_time) { + r['WAMR_aot'] = wamr_aot_time.toFixed(2) + 'ms'; } - if (js_time) { - r['QuickJS'] = js_time.toFixed(2) + 'ms'; + if (qjs_js_time) { + r['QuickJS'] = qjs_js_time.toFixed(2) + 'ms'; } - if (ts_time && js_time) { - let ratio = ts_time / js_time; + if (v8_js_time) { + r['Node'] = v8_js_time.toFixed(2) + 'ms'; + } + + if (wamr_interp_time && qjs_js_time) { + let ratio = wamr_interp_time / qjs_js_time; let formatted_result = ratio.toFixed(2); r['WAMR_interpreter/qjs'] = formatted_result; } - if (aot_time && js_time) { - let ratio_aot = aot_time / js_time; + if (wamr_aot_time && qjs_js_time) { + let ratio_aot = wamr_aot_time / qjs_js_time; let formatted_result_aot = ratio_aot.toFixed(2); r['WAMR_aot/qjs'] = formatted_result_aot; } + if (wamr_interp_time && v8_js_time) { + let ratio = wamr_interp_time / v8_js_time; + let formatted_result = ratio.toFixed(2); + r['WAMR_interpreter/node'] = formatted_result; + } + + if (wamr_aot_time && v8_js_time) { + let ratio_aot = wamr_aot_time / v8_js_time; + let formatted_result_aot = ratio_aot.toFixed(2); + r['WAMR_aot/node'] = formatted_result_aot; + } + results.push(r); } diff --git a/tools/validate/run_module_on_node/import_object.js b/tools/validate/run_module/import_object.js similarity index 98% rename from tools/validate/run_module_on_node/import_object.js rename to tools/validate/run_module/import_object.js index d4483921..28f6ceb0 100644 --- a/tools/validate/run_module_on_node/import_object.js +++ b/tools/validate/run_module/import_object.js @@ -286,11 +286,11 @@ const importObject = { } }, env: { - console_log: (obj) => { + Console_log: (obj) => { /** TODO: cant log reference type variable */ console.log(obj); }, - console_constructor: (obj) => {}, + Console_constructor: (obj) => {}, strcmp(a, b) { let lhs = cstringToJsString(a); let rhs = cstringToJsString(b); @@ -298,6 +298,8 @@ const importObject = { }, setTimeout: (obj) => {}, clearTimeout: (obj) => {}, + malloc: (size)=>{}, + free: (size)=>{}, array_push_generic: (ctx, obj, elem) => {}, array_pop_f64: (ctx, obj) => {}, diff --git a/tools/validate/run_module_on_node/run_module_on_node.md b/tools/validate/run_module/readme.md similarity index 73% rename from tools/validate/run_module_on_node/run_module_on_node.md rename to tools/validate/run_module/readme.md index 93c629d9..74f3be20 100644 --- a/tools/validate/run_module_on_node/run_module_on_node.md +++ b/tools/validate/run_module/readme.md @@ -1,12 +1,14 @@ -# Run generated WASM module on Node.js +# Run generated WASM module -This document describes how to execute WASM module on Node.js. +This document describes how to execute WASM module on node.js and on chrome. > Note: Wasmnizer-ts follows the latest WasmGC spec, which requires `V8 v11.9+`, but the latest nodejs (v21.5.0) is using `V8 11.8.172.17`, so currently the generated WASM module can't execute on any nodejs releases. > If you do want to try on nodejs, you can reset to commit `94cf9929421d47a9976fa6edf74b25ef2a00ee12` to build the compiler, which is compatible to older V8 versions. -## Prerequisites +## Run module on node + +### Prerequisites - node.js version 20.0.0 or higher to enable support for `stringref` feature, node.js version 20.0 or higher is necessary. @@ -16,7 +18,7 @@ This document describes how to execute WASM module on Node.js. - `--experimental-wasm-gc`: This flag is required to enable support for the WASM GC feature. - `--experimental-wasm-stringref`: This flag is needed to enable support for the `stringref` feature. -## How to Run +### How to Run To run your WebAssembly file, use the following command: @@ -31,7 +33,7 @@ This document describes how to execute WASM module on Node.js. - `-f`: specify the exported WASM function you want to execute in Node.js. - `-s`: specify to execute the `_start` WASM function to initialize global variables if necessary. -## Example +### Example Here is an example. @@ -52,3 +54,14 @@ This document describes how to execute WASM module on Node.js. ``` it will output `1`. + +## Run module on chrome + +### Prerequisites +- Set chrome flags by `chrome://flags`, should set these flags as enabled: + - Experimental WebAssembly + - WebAssembly Garbage Collection + - WebAssembly Stringref + +### How to Run +Start a server, open the `run_module_on_chrome.html` on chrome, fill in with the wasm path, the wasm function name, and arguments(must be separated by commas), then click `submit` button, and the result will be print on the page. \ No newline at end of file diff --git a/tools/validate/run_module/run_module_on_chrome.html b/tools/validate/run_module/run_module_on_chrome.html new file mode 100644 index 00000000..9bb80a29 --- /dev/null +++ b/tools/validate/run_module/run_module_on_chrome.html @@ -0,0 +1,62 @@ + + + + +
+ +