nandi/vflutter_ffipublic Fork 0
main
Commits
Clone
git clone https://git.rickub.com/nandi/vflutter_ffi.git
git clone ssh://git@rickub.com/nandi/vflutter_ffi.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

check_pool.sh · 117 lines · 4.2 KBBash Blame HistoryRaw
Render in parallel on web, via a pool of Web Workers 4506a58 nandithebull 10h ago1#!/usr/bin/env bash
2# Does the web build actually render in parallel, and does it still produce
3# the right pixels?
4#
5# Both halves matter. A worker pool that silently falls back to one thread
6# looks exactly like a working one except for the clock, and a pool that
7# assembles bands in the wrong order produces a plausible-looking but wrong
8# frame. So this times 1 worker against many and compares both against a
9# straight single-instance render.
10#
11# The page POSTs its results back rather than logging them: headless Chrome's
12# console plumbing is unreliable, and --virtual-time-budget would make
13# performance.now() meaningless for timing anyway.
14set -euo pipefail
15cd "$(dirname "$0")/.."
16
17chrome="${CHROME_EXECUTABLE:-$(command -v google-chrome-stable || command -v google-chrome || command -v chromium || true)}"
18[ -n "$chrome" ] || { echo "no Chrome found; set CHROME_EXECUTABLE"; exit 1; }
19[ -f example/web/nimflutter.js ] || { echo "run 'just wasm' first"; exit 1; }
20
21work="$(mktemp -d)"
22port="${PORT:-8793}"
23profile="$work/profile"
24trap 'rm -rf "$work"' EXIT
25
26cp example/web/nimflutter.js example/web/nimflutter.wasm \
27 example/web/nimflutter_worker.js example/web/nimflutter_pool.js "$work/"
28
29cat > "$work/index.html" <<'HTML'
30<!DOCTYPE html><meta charset="utf-8"><title>pool</title>
31<script src="nimflutter.js"></script>
32<script src="nimflutter_pool.js"></script>
33<script type="module">
34const W = 800, H = 600, ITER = 500;
35const SIG = Array(10).fill('number');
36const report = (lines) =>
37 fetch('/result', {method: 'POST', body: lines.join('\n')});
38
39try {
40 // Ground truth: one instance, one band, on the main thread.
41 const M = await createNimFlutterModule();
42 M.ccall('nf_init', null, [], []);
43 const n = W * H * 4;
44 const p = M._malloc(n);
45 const t0 = performance.now();
46 M.ccall('nf_mandelbrot', null, SIG, [p, n, W, H, -0.5, 0.0, 3.0, ITER, 0, H]);
47 const serialMs = performance.now() - t0;
48 const truth = M.HEAPU8.slice(p, p + n);
49 M._free(p);
50
51 const timed = async (tiles) => {
52 await nimflutterRenderParallel(W, H, -0.5, 0.0, 3.0, ITER, tiles); // warm
53 const t = performance.now();
54 const out = await nimflutterRenderParallel(W, H, -0.5, 0.0, 3.0, ITER, tiles);
55 return {ms: performance.now() - t, out};
56 };
57
58 const diff = (a, b) => {
59 if (a.length !== b.length) return -1;
60 let d = 0;
61 for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) d++;
62 return d;
63 };
64
65 const one = await timed(1);
66 const many = await timed(32);
67
68 await report([
69 `cores=${navigator.hardwareConcurrency} workers=${nimflutterPoolSize()}`,
70 `main-thread=${serialMs.toFixed(1)}ms`,
71 `1-worker=${one.ms.toFixed(1)}ms`,
72 `32-bands=${many.ms.toFixed(1)}ms`,
73 `speedup=${(one.ms / many.ms).toFixed(2)}x`,
74 `diff-1worker=${diff(truth, one.out)}`,
75 `diff-pool=${diff(truth, many.out)}`,
76 ]);
77} catch (e) {
78 await report([`error=${e && e.message ? e.message : e}`]);
79}
80</script>
81HTML
82
83# Serves the directory, and exits after the page POSTs its results to /result.
84cat > "$work/server.py" <<'PY'
85import sys, http.server
86out = sys.argv[1]
87class H(http.server.SimpleHTTPRequestHandler):
88 def do_POST(self):
89 body = self.rfile.read(int(self.headers['Content-Length'])).decode()
90 open(out, 'w').write(body)
91 self.send_response(204); self.end_headers()
92 raise SystemExit(0)
93 def log_message(self, *a): pass
94http.server.HTTPServer(('127.0.0.1', int(sys.argv[2])), H).serve_forever()
95PY
96
97(cd "$work" && exec python3 server.py results.txt "$port") >/dev/null 2>&1 &
98sleep 2
99
100"$chrome" --headless=new --no-sandbox --disable-dev-shm-usage \
101 --user-data-dir="$profile" --disable-gpu \
102 "http://127.0.0.1:$port/index.html" >/dev/null 2>&1 &
103chrome_pid=$!
104
105for _ in $(seq 1 60); do
106 [ -s "$work/results.txt" ] && break
107 sleep 1
108done
109kill "$chrome_pid" 2>/dev/null || true
110kill %1 %2 2>/dev/null || true
111
112[ -s "$work/results.txt" ] || { echo "FAIL page produced no result"; exit 1; }
113{ cat "$work/results.txt"; echo; }
114grep -q '^error=' "$work/results.txt" && { echo "FAIL page threw"; exit 1; }
115grep -q 'diff-1worker=0' "$work/results.txt" || { echo "FAIL 1-worker frame differs"; exit 1; }
116grep -q 'diff-pool=0' "$work/results.txt" || { echo "FAIL pooled frame differs"; exit 1; }
117echo "ok pooled and single-instance frames are identical"