Files
2nd/10_Wiki/Topics/Architecture/Old_Space.md
T
koriweb d8a80f6272 chore(wiki): dangling 링크 canonical 정규화 (768파일/1200건)
이름만 다른(표기 변형) [[위키링크]]를 대상 문서의 canonical 제목으로 치환해
끊겼던 1,200개 링크를 연결. 제목/파일명 정규화 일치만 적용하고 별칭 매칭은
과병합 위험으로 제외(애매성 가드). 원본은 _link_reconcile_backup/ 에 백업.
도구: Datacollect/scripts/link_reconcile_apply.mjs

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 12:24:15 +09:00

5.4 KiB

id, title, category, status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, verification_status, tags, raw_sources, last_reinforced, github_commit, tech_stack
id title category status canonical_id aliases duplicate_of source_trust_level confidence_score verification_status tags raw_sources last_reinforced github_commit tech_stack
wiki-2026-0508-old-space Old Space (V8) 10_Wiki/Topics verified self
Old Generation
Tenured Space
V8 Old Space
Major GC heap
none A 0.95 applied
v8
gc
memory
javascript
runtime
2026-05-10 pending
language framework
javascript v8

Old Space (V8)

매 한 줄

"매 V8 heap의 long-lived object 영역 — Young Gen에서 2번 생존 후 promote, Major GC (Mark-Compact / Mark-Sweep / Concurrent Marking) 대상.". Generational hypothesis 기반 (Ungar 1984). 2026 현재 V8 13.x · Node 24 · Chrome 130+에서 Orinoco의 concurrent / parallel / incremental marking + Pointer Compression으로 pause time <1ms.

매 핵심

매 V8 heap 구조

  • New Space (Young Gen): 1-8MB, semi-space (Cheney scavenger), allocation 빠름.
  • Old Space (Old Gen): 매 default unbounded (--max-old-space-size 제한), promote target.
  • Code Space: JIT compiled code.
  • Map Space: Hidden class (V8 maps).
  • Large Object Space: ≥ ~256KB single object.
  • Read-Only Space: immutable roots.

매 promotion 규칙

  • 매 Young Gen에서 minor GC 2번 survive → Old Space promote.
  • Large object (≥ kMaxRegularHeapObjectSize, ~256KB) → 직접 Old Space (LOS).

매 Major GC (Old Space) 알고리즘

  • Mark-Compact: full pause, fragmentation 제거.
  • Concurrent Marking (Orinoco): worker thread가 mark, main thread continue.
  • Incremental Marking: chunk별 mark, 사이사이 mutator 실행.
  • Lazy Sweeping: page별로 sweep on demand.

매 응용

  1. Node.js server — heap profiling으로 leak 추적 (--inspect, heapdump).
  2. Chrome — DevTools Memory tab의 retained size 분석.
  3. Performance tuning — --max-old-space-size=4096로 limit 조정.

💻 패턴

Heap snapshot 생성 (Node.js)

import { writeHeapSnapshot } from 'node:v8';
import { performance } from 'node:perf_hooks';

process.on('SIGUSR2', () => {
  const file = `/tmp/heap-${Date.now()}.heapsnapshot`;
  writeHeapSnapshot(file);
  console.log('snapshot:', file);
});
// kill -USR2 <pid>

Inspect heap stats

import v8 from 'node:v8';
console.log(v8.getHeapSpaceStatistics());
// [ { space_name: 'old_space', space_size, space_used_size, ... } ]

console.log(v8.getHeapStatistics());
// { total_heap_size, used_heap_size, heap_size_limit, ... }

Force GC for measurement (--expose-gc)

// node --expose-gc app.js
function measureRetained(fn) {
  global.gc(); global.gc();
  const before = process.memoryUsage().heapUsed;
  const ref = fn();
  global.gc(); global.gc();
  const after = process.memoryUsage().heapUsed;
  return { ref, retained: after - before };
}

Trace GC events

node --trace-gc --trace-gc-verbose app.js
# [12345:0x...] [GC] 100ms: 50.0 (60.0) -> 30.0 (60.0) MB (Mark-Sweep) ...

Monitor old space in production (Prometheus)

import client from 'prom-client';
import v8 from 'node:v8';

const oldSpaceUsed = new client.Gauge({
  name: 'nodejs_v8_old_space_used_bytes',
  help: 'V8 old space used',
});
setInterval(() => {
  const old = v8.getHeapSpaceStatistics()
    .find(s => s.space_name === 'old_space');
  oldSpaceUsed.set(old.space_used_size);
}, 5000);

Avoid old-space leak — WeakRef / WeakMap for cache

const cache = new WeakMap();  // key not retained
function compute(obj) {
  if (cache.has(obj)) return cache.get(obj);
  const v = expensive(obj);
  cache.set(obj, v);
  return v;
}
// obj GC'd → cache entry auto-removed

매 결정 기준

상황 Approach
Suspected memory leak heap snapshot diff
OOM under load --max-old-space-size= increase + investigate
Frequent major GC pause reduce promotion rate (avoid long-lived churn)
Cache growing forever WeakMap / LRU bound
Need pre-prod heap profile --inspect + DevTools

기본값: 매 default V8 settings — limit 변경은 측정 후.

🔗 Graph

🤖 LLM 활용

언제: Node.js memory issue 분석, heap profiling, V8 internals 학습, GC tuning. 언제 X: non-V8 runtime (Bun-JSC, Deno-V8 다르지만 비슷, Hermes는 별도), browser-only DOM leak (different territory).

안티패턴

  • Forgotten timer/listener: 매 closure가 old space에 retain.
  • Global cache without bound: 매 monotonic growth → OOM.
  • Large allocation in hot loop: Young → Old promotion 폭증, frequent major GC.
  • String concat in loop without builder: 매 intermediate retained.
  • --max-old-space-size blindly raised: 매 leak hide, root cause 회피.

🧪 검증 / 중복

  • Verified (V8 source v8/src/heap/, V8 blog Orinoco posts, Node.js v8 module docs 2026).
  • 신뢰도 A.
  • Duplicates: Old_Space(Old_Generation).md redirects here.

🕓 Changelog

날짜 변경
2026-05-08 Phase 1
2026-05-10 Manual cleanup — canonical V8 Old Space doc + heap profiling patterns