--- id: wiki-2026-0508-cpu-overhead title: CPU Overhead category: 10_Wiki/Topics status: verified canonical_id: self aliases: [CPU Cost, JS Main Thread Cost] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [performance, cpu, main-thread, profiling] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: JavaScript framework: Browser/Node --- # CPU Overhead ## 매 한 줄 > **"매 main thread 매 free 매 fast UI"**. CPU overhead는 JS execution / parsing / hydration / re-render에 소비되는 main-thread time — 이게 길어지면 INP가 무너지고 user input이 lag한다. 2026 INP가 LCP를 대체한 third Core Web Vital이 되어 CPU profile + scheduling이 frontend 의 first concern. ## 매 핵심 ### 매 source - **Parse + compile**: download된 JS bytes → AST → bytecode (V8 측정 시 KB 당 ~1ms low-end mobile). - **Hydration**: SSR HTML 위 React/Vue 매 attach. - **Re-render**: state change → diff → DOM commit. - **Long task** (>50ms): block input. ### 매 측정 - Chrome Performance panel — flame chart, "Long tasks". - `PerformanceObserver` API on `longtask`. - React Profiler / Vue Devtools timeline. - Web Vitals — INP, TBT. ### 매 응용 1. JS payload 줄이기 → less parse. 2. Hydration partial / streaming. 3. Heavy work → Web Worker / requestIdleCallback / startTransition. ## 💻 패턴 ### Long task observer ```ts const obs = new PerformanceObserver((list) => { for (const entry of list.getEntries()) { if (entry.duration > 50) { console.warn(`Long task: ${entry.duration.toFixed(0)}ms`, entry); } } }); obs.observe({ type: 'longtask', buffered: true }); ``` ### Yield to main thread ```ts function yieldToMain() { return new Promise(resolve => setTimeout(resolve, 0)); } async function processChunks(items: Item[]) { for (let i = 0; i < items.length; i++) { process(items[i]); if (i % 100 === 0) await yieldToMain(); } } ``` ### scheduler.yield (Chrome 129+) ```ts async function processBig(items: Item[]) { for (const item of items) { process(item); if ('scheduler' in window && 'yield' in (window as any).scheduler) { await (window as any).scheduler.yield(); } } } ``` ### Web Worker offload ```ts // worker.ts self.onmessage = (e) => { const result = heavyTransform(e.data); self.postMessage(result); }; // main.ts const w = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' }); w.postMessage(largeData); w.onmessage = (e) => render(e.data); ``` ### React startTransition ```tsx import { startTransition, useState } from 'react'; function Search() { const [q, setQ] = useState(''); const [results, setResults] = useState([]); function onChange(e) { setQ(e.target.value); // urgent startTransition(() => { setResults(filter(allItems, e.target.value)); // background }); } return ; } ``` ### useDeferredValue ```tsx function Page({ filter }) { const deferredFilter = useDeferredValue(filter); const items = useMemo(() => filterBig(deferredFilter), [deferredFilter]); return ; } ``` ### requestIdleCallback for non-critical ```ts const work = [...]; function schedule() { if (!work.length) return; requestIdleCallback((deadline) => { while (work.length && deadline.timeRemaining() > 0) { doOne(work.shift()); } schedule(); }); } schedule(); ``` ### Avoid layout thrash ```ts // X — 매 read after write 매 force reflow els.forEach(el => { el.style.width = '100px'; console.log(el.offsetWidth); // forced sync layout }); // O — 매 batch read, batch write const widths = els.map(el => el.offsetWidth); els.forEach((el, i) => el.style.width = widths[i] + 1 + 'px'); ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | Heavy compute (parse/transform) | Web Worker | | Long list render | virtualization (TanStack Virtual) | | Filter on input | useDeferredValue / startTransition | | Background prefetch | requestIdleCallback | | Animation | CSS / RAF, no JS-driven layout | **기본값**: measure → smallest fix → re-measure. ## 🔗 Graph - 부모: [[Frontend Performance]] · [[Core Web Vitals Optimization (INP, LCP, CLS)|Core Web Vitals]] - 변형: [[INP]] - 응용: [[Web Worker]] · [[Concurrent Features|Concurrent Rendering]] - Adjacent: [[Bundle Size Optimization]] · [[Hydration]] ## 🤖 LLM 활용 **언제**: long task identification, scheduler API generation, INP debug script. **언제 X**: real device profiling — DevTools / WebPageTest 필수. ## ❌ 안티패턴 - **JS-driven animation**: setInterval + style 변경 — RAF / CSS 사용. - **Sync XMLHttpRequest**: 매 main block — fetch async 사용. - **Force layout in loop**: read after write — batch. - **Hydration of static page**: islands / partial hydration. - **Massive context provider**: 매 모든 child re-render — split context. ## 🧪 검증 / 중복 - Verified (web.dev INP guide, Chrome scheduler API, React 19 docs). - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — CPU overhead pattern + scheduler API |