memory-snapshot.ts
73 lines · browse/src/memory-snapshot.ts at 3f79d81
1// Shared types for the $B memory diagnostic command and the /memory
2// endpoint. Lives in its own module so server.ts, read-commands.ts, and
3// the extension footer poll can import without taking a circular dep on
4// browser-manager.ts.
5//
6// Background: the gbrowser-OOM investigation (160 GB Activity Monitor
7// reading on a friend's machine) needed a diagnostic that could land
8// before the next incident — measurement comes first, fixes come after.
9// $B memory is that diagnostic.
11/** Counts/bytes for the bounded in-memory structures on the Bun side. */
12export interface MemoryStructureStats {
13 modificationHistory: { current: number; cap: number; evicted: number };
14 activitySubscribers: number;
15 inspectorSubscribers: number;
16 consoleBufferLen: number;
17 networkBufferLen: number;
18 dialogBufferLen: number;
19 captureBufferBytes: number;
20}
22/** Per-tab JS heap snapshot (CDP Performance.getMetrics). */
23export interface MemoryTabSnapshot {
24 id: number;
25 url: string;
26 title: string;
27 jsHeapUsed: number;
28 jsHeapTotal: number;
29 documents: number;
30 nodes: number;
31 listeners: number;
32}
34/** Chromium process metadata via CDP SystemInfo.getProcessInfo. */
35export interface MemoryProcess {
36 /** Chromium-internal process id (not OS PID). */
37 id: number;
38 /** 'browser' | 'renderer' | 'gpu' | 'utility' | 'extension' | ... */
39 type: string;
40 /** CPU time accumulated since process start (seconds). */
41 cpuTime: number;
42}
44export interface MemorySnapshot {
45 bunServer: {
46 rss: number;
47 heapUsed: number;
48 heapTotal: number;
49 external: number;
50 };
51 tabs: MemoryTabSnapshot[];
52 /**
53 * Chromium process tree. `null` when no browser handle is available
54 * (server in connection mode, or browser not yet launched).
55 *
56 * Per-process RSS is NOT included: SystemInfo.getProcessInfo returns
57 * id+type+cpuTime but Chromium does not expose RSS via CDP. The
58 * `notes[]` field tells the caller why — see the follow-up TODO
59 * "native/GPU memory breakdown" for the deferred fix.
60 */
61 processes: MemoryProcess[] | null;
62 structures: MemoryStructureStats;
63 capturedAt: number;
64 notes: string[];
65}
67/** Format bytes as a short human string ("1.4 GB", "312 MB", "84 KB"). */
68export function formatBytes(n: number): string {
69 if (n < 1024) return `${n} B`;
70 if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
71 if (n < 1024 * 1024 * 1024) return `${(n / 1024 / 1024).toFixed(1)} MB`;
72 return `${(n / 1024 / 1024 / 1024).toFixed(2)} GB`;
73}