/ proof-of-concept / cymsimweb
Sign in
proof-of-concept / cymsimweb
cymsimweb / src / run.ts
47 lines · 2.2 KBCodeBlameHistory
1e29264cymsimweb: WebGPU companion of cymsim with YAML/form editor, live spectrogram and playbackJeremy Magland 1// Drives a simulator backend chunk by chunk with an adaptive chunk size, pausing and stopping on
2// request, and reports pressure chunks, diagnostics and progress to the UI.
3import type { Setup } from "./model/setup.ts";
4import type { ChunkResult, Diagnostics, SimulatorBackend } from "./model/simulator.ts";
6export interface RunCallbacks {
7 onChunk(res: ChunkResult): void;
8 onDiagnostics(d: Diagnostics): void;
9 onProgress(samplesDone: number, wallSeconds: number): void;
10 onDone(stopped: boolean): void;
13export class Runner {
14 private paused = false; private stopped = false; private resume: (() => void) | null = null;
15 private chunk = 512;
16 readonly backend: SimulatorBackend; readonly setup: Setup; private readonly cb: RunCallbacks;
18 constructor(backend: SimulatorBackend, setup: Setup, cb: RunCallbacks) { this.backend = backend; this.setup = setup; this.cb = cb; }
20 async run() {
21 const { setup, backend } = this, t0 = performance.now();
22 let lastDiag = t0;
23 while (!this.stopped && backend.samplesDone < setup.nSamples) {
24 if (this.paused) await new Promise<void>((r) => { this.resume = r; });
25 if (this.stopped) break;
3534482Linear spectrogram axis by default; capture and replay the displacement movie at a chosen slowdownJeremy Magland 26 const n = Math.min(this.chunk, backend.maxChunk, setup.nSamples - backend.samplesDone);
28 const res = await backend.runChunk(n);
29 const dtc = (performance.now() - tc) / 1000;
30 // aim at about 0.4 s of wall time per chunk, in multiples of 128 samples, at most 8192
3534482Linear spectrogram axis by default; capture and replay the displacement movie at a chosen slowdownJeremy Magland 31 this.chunk = Math.max(128, Math.min(backend.maxChunk, Math.round((n * 0.4) / Math.max(dtc, 1e-3) / 128) * 128));
33 this.cb.onProgress(backend.samplesDone, (performance.now() - t0) / 1000);
34 if (performance.now() - lastDiag > 1000 || backend.samplesDone >= setup.nSamples) {
35 this.cb.onDiagnostics(await backend.diagnostics());
36 lastDiag = performance.now();
37 }
38 await new Promise((r) => setTimeout(r, 0));
39 }
40 this.cb.onDone(this.stopped);
41 }
43 pause() { this.paused = true; }
44 unpause() { this.paused = false; this.resume?.(); this.resume = null; }
45 stop() { this.stopped = true; this.unpause(); }
46 get isPaused() { return this.paused; }
↑↓ move↵openescclose