From ce9075e8bf3e779f9f9117e19e30b0210cf1d2c7 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Mon, 28 Apr 2025 07:46:20 -0700 Subject: [PATCH] Add a codesize test for AUDIO_WORKLET I want to get baseline before landing #24190 --- test/code_size/audio_worklet_wasm.js | 176 +++++++++++++++++++++++++ test/code_size/audio_worklet_wasm.json | 12 ++ test/test_other.py | 13 +- 3 files changed, 196 insertions(+), 5 deletions(-) create mode 100644 test/code_size/audio_worklet_wasm.js create mode 100644 test/code_size/audio_worklet_wasm.json diff --git a/test/code_size/audio_worklet_wasm.js b/test/code_size/audio_worklet_wasm.js new file mode 100644 index 0000000000000..5a9edc30e1cea --- /dev/null +++ b/test/code_size/audio_worklet_wasm.js @@ -0,0 +1,176 @@ +var g = globalThis.Module || "undefined" != typeof Module ? Module : {}, k = "undefined" !== typeof AudioWorkletGlobalScope, m = "em-ww" == globalThis.name, n, p, q, r, t, x, U, V, A, Q, C, W; + +m && !k && (onmessage = a => { + onmessage = null; + a = a.data; + g ||= {}; + Object.assign(g, a); + t = a.mem; + u(); + v(); + a.wasm = a.mem = 0; +}); + +function u() { + var a = t.buffer; + p = new Uint8Array(a); + n = new Int32Array(a); + g.HEAPU32 = q = new Uint32Array(a); + g.HEAPF32 = r = new Float32Array(a); +} + +if (k || !m) t = g.mem || new WebAssembly.Memory({ + initial: 256, + maximum: 256, + shared: !0 +}), u(); + +var w = [], y = a => { + a = a.data; + let b = a._wsc; + b && x.get(b)(...a.x); +}, z = a => { + w.push(a); +}, B = a => A(a), D = () => C(), G = (a, b, c, e) => { + b = E[b]; + E[a].connect(b.destination || b, c, e); +}, E = {}, H = 0, I = "undefined" != typeof TextDecoder ? new TextDecoder : void 0, J = (a = 0) => { + for (var b = p, c = a + NaN, e = a; b[e] && !(e >= c); ) ++e; + if (16 < e - a && b.buffer && I) return I.decode(b.slice(a, e)); + for (c = ""; a < e; ) { + var d = b[a++]; + if (d & 128) { + var h = b[a++] & 63; + if (192 == (d & 224)) c += String.fromCharCode((d & 31) << 6 | h); else { + var f = b[a++] & 63; + d = 224 == (d & 240) ? (d & 15) << 12 | h << 6 | f : (d & 7) << 18 | h << 12 | f << 6 | b[a++] & 63; + 65536 > d ? c += String.fromCharCode(d) : (d -= 65536, c += String.fromCharCode(55296 | d >> 10, 56320 | d & 1023)); + } + } else c += String.fromCharCode(d); + } + return c; +}, K = a => { + var b = window.AudioContext || window.webkitAudioContext; + if (a >>= 2) { + var c = q[a] ? (c = q[a]) ? J(c) : "" : void 0; + a = { + latencyHint: c, + sampleRate: n[a + 1] || void 0 + }; + } else a = void 0; + if (c = b) b = new b(a), E[++H] = b, c = H; + return c; +}, L = (a, b, c, e, d) => { + if (c >>= 2) { + var h = n[c], f = n[c + 1]; + if (q[c + 2]) { + var l = q[c + 2] >> 2; + c = n[c + 1]; + let F = []; + for (;c--; ) F.push(q[l++]); + l = F; + } else l = void 0; + e = { + numberOfInputs: h, + numberOfOutputs: f, + outputChannelCount: l, + processorOptions: { + cb: e, + ud: d, + sc: 128 + } + }; + } else e = void 0; + a = new AudioWorkletNode(E[a], b ? J(b) : "", e); + E[++H] = a; + return H; +}, M = (a, b, c, e) => { + b >>= 2; + let d = [], h = q[b + 1], f = q[b + 2] >> 2, l = 0; + for (;h--; ) d.push({ + name: l++, + defaultValue: r[f++], + minValue: r[f++], + maxValue: r[f++], + automationRate: [ "a", "k" ][q[f++]] + "-rate" + }); + h = E[a].audioWorklet.s.port; + f = h.postMessage; + b = (b = q[b]) ? J(b) : ""; + f.call(h, { + _wpn: b, + ap: d, + ch: a, + cb: c, + ud: e + }); +}, N = () => !1, O = 1, P = a => { + a = a.data; + let b = a._wsc; + b && x.get(b)(...a.x); +}, R = a => Q(a), S = (a, b, c, e, d) => { + let h = E[a], f = h.audioWorklet, l = () => { + x.get(e)(a, 0, d); + }; + if (!f) return l(); + f.addModule("a.aw.js").then((() => { + f.s = new AudioWorkletNode(h, "message", { + processorOptions: { + $ww: O++, + wasm: g.wasm, + mem: t, + sb: b, + sz: c + } + }); + f.s.port.onmessage = P; + return f.addModule(g.js); + })).then((() => { + x.get(e)(a, 1, d); + })).catch(l); +}; + +function T(a) { + let b = document.createElement("button"); + b.innerHTML = "Toggle playback"; + document.body.appendChild(b); + a = E[a]; + b.onclick = () => { + "running" != a.state ? a.resume() : a.suspend(); + }; +} + +function v() { + U = { + f: T, + g: G, + d: K, + h: L, + e: M, + b: N, + c: S, + a: t + }; + WebAssembly.instantiate(g.wasm, { + a: U + }).then((a => { + a = a.instance.exports; + V = a.j; + A = a.l; + Q = a.m; + C = a.n; + W = a.o; + x = a.k; + g.stackSave = D; + g.stackAlloc = R; + g.stackRestore = B; + g.wasmTable = x; + m ? (a = g, W(a.sb, a.sz), "undefined" === typeof AudioWorkletGlobalScope && (removeEventListener("message", z), + w = w.forEach(y), addEventListener("message", y))) : a.i(); + m || V(); + })); +} + +k && v(); + +m || v(); \ No newline at end of file diff --git a/test/code_size/audio_worklet_wasm.json b/test/code_size/audio_worklet_wasm.json new file mode 100644 index 0000000000000..8a2a82cbfbe83 --- /dev/null +++ b/test/code_size/audio_worklet_wasm.json @@ -0,0 +1,12 @@ +{ + "a.html": 519, + "a.html.gz": 364, + "a.js": 2851, + "a.js.gz": 1583, + "a.aw.js": 2551, + "a.aw.js.gz": 922, + "a.wasm": 1287, + "a.wasm.gz": 859, + "total": 7208, + "total_gz": 3728 +} diff --git a/test/test_other.py b/test/test_other.py index d2158985416e5..167071e76d2c5 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -11725,6 +11725,7 @@ def test_function_exports_are_small(self, args, opt, closure): self.assertEqual(num_times_export_is_referenced, 1) @parameterized({ + 'audio_worklet': ('audio_worklet', False, True), 'hello_world_wasm': ('hello_world', False, True), 'hello_world_wasm2js': ('hello_world', True, True), 'random_printf_wasm': ('random_printf', False), @@ -11739,7 +11740,7 @@ def test_function_exports_are_small(self, args, opt, closure): 'hello_embind': ('embind_hello', False), }) @crossplatform - def test_minimal_runtime_code_size(self, test_name, js, compare_js_output=False): + def test_minimal_runtime_code_size(self, test_name, wasm2js, compare_js_output=False): smallest_code_size_args = ['-sMINIMAL_RUNTIME=2', '-sENVIRONMENT=web', '-sTEXTDECODER=2', @@ -11763,8 +11764,6 @@ def test_minimal_runtime_code_size(self, test_name, js, compare_js_output=False) '-DNDEBUG', '-ffast-math'] - wasm2js = ['-sWASM=0'] - math_sources = [test_file('code_size/math.c')] hello_world_sources = [test_file('small_hello_world.c'), '-sMALLOC=none'] @@ -11778,6 +11777,7 @@ def test_minimal_runtime_code_size(self, test_name, js, compare_js_output=False) '-sMODULARIZE'] hello_webgl2_sources = hello_webgl_sources + ['-sMAX_WEBGL_VERSION=2'] hello_wasm_worker_sources = [test_file('wasm_worker/wasm_worker_code_size.c'), '-sWASM_WORKERS', '-sENVIRONMENT=web,worker'] + audio_worklet_sources = [test_file('webaudio/audioworklet.c'), '-sWASM_WORKERS', '-sAUDIO_WORKLET', '-sENVIRONMENT=web,worker', '-sTEXTDECODER=1'] embind_hello_sources = [test_file('code_size/embind_hello_world.cpp'), '-lembind'] embind_val_sources = [test_file('code_size/embind_val_hello_world.cpp'), '-lembind', @@ -11792,6 +11792,7 @@ def test_minimal_runtime_code_size(self, test_name, js, compare_js_output=False) 'math': math_sources, 'hello_webgl2': hello_webgl2_sources, 'hello_wasm_worker': hello_wasm_worker_sources, + 'audio_worklet': audio_worklet_sources, 'embind_val': embind_val_sources, 'embind_hello': embind_hello_sources, }[test_name] @@ -11802,11 +11803,13 @@ def print_percent(actual, expected): return ' ({:+.2f}%)'.format((actual - expected) * 100.0 / expected) outputs = ['a.html', 'a.js'] + if '-sAUDIO_WORKLET' in sources: + outputs += ['a.aw.js'] args = smallest_code_size_args[:] - if js: - args += wasm2js + if wasm2js: + args += ['-sWASM=0'] test_name += '_wasm2js' else: outputs += ['a.wasm']