diff options
| author | Adam Soltys <[email protected]> | 2026-09-09 22:46:20 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-09-09 22:46:20 -0700 |
| commit | 95cd3fa81097e288e4920bb5029cfd23f7cae98f (patch) | |
| tree | 1ab5418098542f77de2d5ee1ddfac9984d1f758e /tools/cdp-callers.js | |
| parent | 9f2ce90f494a5b415bec0898e3185437126fc7d9 (diff) | |
| download | coinosv3-95cd3fa81097e288e4920bb5029cfd23f7cae98f.tar.gz coinosv3-95cd3fa81097e288e4920bb5029cfd23f7cae98f.zip | |
tools: CDP main-thread profiler for the live app (laptop or phone over adb).
cdp-profile.js samples the page through the remote-debugging port around a
reload / simulated refocus / manual action, and can serve a local dist into
the real tab (service worker bypassed) to profile a fix before it ships.
cdp-callers.js answers "who calls X" from the saved profile.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Nw1Dijik1tLVKRM1WkU7xE
Diffstat (limited to 'tools/cdp-callers.js')
| -rw-r--r-- | tools/cdp-callers.js | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/tools/cdp-callers.js b/tools/cdp-callers.js new file mode 100644 index 0000000..2573df4 --- /dev/null +++ b/tools/cdp-callers.js @@ -0,0 +1,19 @@ +// Who calls a hot function? Aggregates ancestor chains (inclusive-time +// weighted) for every profile node named <fnName>, from a .cpuprofile saved +// by tools/cdp-profile.js --out. +const [file, name, depthS] = process.argv.slice(2); const depth = Number(depthS || 6); +const p = JSON.parse(await Bun.file(file).text()); +const nodes = new Map(p.nodes.map((n) => [n.id, n])); const parent = new Map(); +for (const n of p.nodes) for (const c of n.children || []) parent.set(c, n.id); +const self = new Map(); for (let i = 0; i < p.samples.length; i++) self.set(p.samples[i], (self.get(p.samples[i]) || 0) + (p.timeDeltas[i + 1] || 0)); +const key = (n) => { const f = n.callFrame; return `${f.functionName || '(anon)'}@${f.url.replace(/^https?:\/\/[^/]+\//, '').slice(0, 22)}:${f.lineNumber + 1}:${f.columnNumber + 1}`; }; +const chains = new Map(); +for (const n of p.nodes) { + if (n.callFrame.functionName !== name) continue; + // inclusive time of this node = sum self of subtree + let total = 0; const stack = [n.id]; while (stack.length) { const id = stack.pop(); total += self.get(id) || 0; for (const c of nodes.get(id).children || []) stack.push(c); } + if (!total) continue; + const path = []; let pid = parent.get(n.id); while (pid != null && path.length < depth) { path.push(key(nodes.get(pid))); pid = parent.get(pid); } + const k = path.join(' <- '); chains.set(k, (chains.get(k) || 0) + total); +} +for (const [k, v] of [...chains].sort((a, b) => b[1] - a[1]).slice(0, 8)) console.log((v / 1000).toFixed(1).padStart(7) + 'ms ' + k); |
