Skip to content

Commit a2149ef

Browse files
unamedkrclaude
andauthored
fix(wasm): eliminate UI hang during prompt prefill (#30)
The browser froze for 5-15s after pressing Enter because the prefill loop (running all prompt tokens through 28 layers) had no yield points. ASYNCIFY sleep only fired during token generation, not prefill. Two fixes: 1. quant.h: add emscripten_sleep(0) every 2 tokens in the prefill loop. Browser can repaint and stays responsive. Only active on __EMSCRIPTEN__ builds — native is unaffected. 2. index.html: double-requestAnimationFrame before WASM call ensures "Thinking..." indicator paints before any blocking starts. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 5f06417 commit a2149ef

File tree

4 files changed

+13
-2
lines changed

4 files changed

+13
-2
lines changed

quant.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15461,9 +15461,15 @@ int tq_generate(tq_model_t* model, tq_tokenizer_t* tokenizer,
1546115461
fprintf(stderr, "\n");
1546215462
}
1546315463

15464-
/* Prefill: process all prompt tokens */
15464+
/* Prefill: process all prompt tokens.
15465+
* On Emscripten with ASYNCIFY, yield every 2 tokens so the browser
15466+
* can repaint (shows "Thinking..." and avoids "page unresponsive"). */
1546515467
for (int i = 0; i < n_prompt; i++) {
1546615468
tq_forward(model, state, prompt_tokens[i], i);
15469+
#ifdef __EMSCRIPTEN__
15470+
extern void emscripten_sleep(unsigned int ms);
15471+
if (i % 2 == 1) emscripten_sleep(0);
15472+
#endif
1546715473
}
1546815474

1546915475
/* Repetition penalty setup */

wasm/index.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,11 @@ <h2>LLM in Your Browser</h2>
448448
};
449449

450450
const chatPrompt = getChatPrompt(text);
451+
452+
// Ensure "Thinking..." paints before WASM blocks the thread.
453+
// Double-rAF guarantees the browser completes one paint cycle.
454+
await new Promise(r => requestAnimationFrame(() => requestAnimationFrame(r)));
455+
451456
const promptPtr = Module.allocateUTF8(chatPrompt);
452457
try {
453458
await Module._wasm_generate_async(promptPtr, 0.7, 256);

wasm/quant.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

wasm/quant.wasm

48 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)