fix: prevent page unresponsive crashes from WebGL GPU stalls during session switch

Reduce terminal chunk size from 128KB to 32KB and use double-RAF between
chunks to give the WebGL renderer time to flush GPU operations. Also switch
cached buffer restore from direct terminal.write() to chunked writes —
the synchronous 256KB write was blocking the main thread for 5+ seconds
via synchronous ReadPixels calls.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
arkon
2026-03-04 13:09:10 +01:00
co-authored by Claude Opus 4.6
parent 9433de75b8
commit c7cd4f9e17
2 changed files with 9 additions and 5 deletions
+8 -4
View File
@@ -1368,8 +1368,9 @@ class CodemanApp {
this.terminal.write(chunk);
offset += chunkSize;
// Schedule next chunk on next frame
requestAnimationFrame(writeChunk);
// Double-RAF: yields to both the browser's layout/paint AND the WebGL renderer's
// GPU flush. Single RAF can still block if ReadPixels is synchronous.
requestAnimationFrame(() => requestAnimationFrame(writeChunk));
};
// Start writing
@@ -3436,12 +3437,15 @@ class CodemanApp {
// belt-and-suspenders guard for any edge cases.
this._restoringFlushedState = true;
try {
// Instant cache restore — show previous buffer immediately while network fetch runs
// Instant cache restore — show previous buffer via chunked write to avoid WebGL GPU stalls.
// Direct terminal.write() of large cached buffers (256KB+) can block the main thread
// for 5+ seconds while the WebGL renderer processes ReadPixels synchronously.
const cachedBuffer = this.terminalBufferCache.get(sessionId);
if (cachedBuffer) {
this.terminal.clear();
this.terminal.reset();
this.terminal.write(cachedBuffer);
await this.chunkedTerminalWrite(cachedBuffer);
if (selectGen !== this._selectGeneration) { this._restoringFlushedState = false; return; }
this.terminal.scrollToBottom();
}
+1 -1
View File
@@ -52,7 +52,7 @@ const TITLE_FLASH_INTERVAL_MS = 1500; // Title flash rate
const BROWSER_NOTIF_RATE_LIMIT_MS = 3000; // Rate limit for browser notifications
const AUTO_CLOSE_NOTIFICATION_MS = 8000; // Auto-close browser notifications
const THROTTLE_DELAY_MS = 100; // General UI throttle delay
const TERMINAL_CHUNK_SIZE = 128 * 1024; // 128KB chunks for terminal data
const TERMINAL_CHUNK_SIZE = 32 * 1024; // 32KB chunks for terminal data (smaller to avoid WebGL GPU stalls)
const TERMINAL_TAIL_SIZE = 256 * 1024; // 256KB tail for initial load
const SYNC_WAIT_TIMEOUT_MS = 50; // Wait timeout for terminal sync
const STATS_POLLING_INTERVAL_MS = 2000; // System stats polling