160 lines
5.1 KiB
Markdown
160 lines
5.1 KiB
Markdown
---
|
|
id: wiki-20260508-reachability-analysis-redir
|
|
title: Reachability Analysis
|
|
category: 10_Wiki/Topics
|
|
status: verified
|
|
canonical_id: self
|
|
aliases: [reachability, GC reachability, mark-and-sweep reachability]
|
|
duplicate_of: none
|
|
source_trust_level: A
|
|
confidence_score: 0.92
|
|
verification_status: applied
|
|
tags: [gc, memory, algorithm, runtime]
|
|
raw_sources: []
|
|
last_reinforced: 2026-05-10
|
|
github_commit: pending
|
|
tech_stack:
|
|
language: JavaScript/C++
|
|
framework: V8
|
|
---
|
|
|
|
# Reachability Analysis
|
|
|
|
## 매 한 줄
|
|
> **"매 GC root 부터 reference graph 의 traverse — reachable object 의 keep, unreachable 의 collect"**. 매 modern GC 의 fundamental algorithm — V8, JVM, .NET, Go 의 동일 원리. 2026 의 incremental + concurrent variant 의 mainstream.
|
|
|
|
## 매 핵심
|
|
|
|
### 매 GC Root 종류
|
|
- **Stack root**: 매 active call stack 의 local variable / parameter.
|
|
- **Global root**: 매 globalThis / window — 매 module-level binding.
|
|
- **Register root**: 매 CPU register 의 held reference.
|
|
- **Compilation root**: 매 V8 의 compiled code 의 reference table.
|
|
- **Handle root**: 매 native binding 의 Handle / Persistent reference.
|
|
|
|
### 매 Traversal algorithm
|
|
- **Tri-color marking**: White (unvisited) → Gray (queued) → Black (done).
|
|
- **Worklist-based**: 매 root 의 enqueue → pop → mark → push referents.
|
|
- **Incremental**: 매 small chunks 의 분할 — 매 main thread pause 의 단축.
|
|
- **Concurrent**: 매 background thread 의 동시 mark — write barrier 의 sync.
|
|
|
|
### 매 응용
|
|
1. V8 의 Mark-Sweep-Compact GC 의 base.
|
|
2. Memory leak 의 발견 — DevTools heap snapshot 의 retainer path.
|
|
3. Cycle detection — refcount 의 약점 의 보완.
|
|
|
|
## 💻 패턴
|
|
|
|
### 매 Reachability 의 tri-color 의 idea
|
|
```javascript
|
|
// 매 conceptual mark phase
|
|
function mark(roots) {
|
|
const gray = new Set(roots); // 매 worklist
|
|
const black = new Set(); // 매 marked
|
|
|
|
while (gray.size > 0) {
|
|
const obj = gray.values().next().value;
|
|
gray.delete(obj);
|
|
black.add(obj);
|
|
|
|
for (const ref of getReferences(obj)) {
|
|
if (!black.has(ref)) gray.add(ref);
|
|
}
|
|
}
|
|
// 매 black = reachable, 매 white (heap - black) = collect
|
|
}
|
|
```
|
|
|
|
### 매 DevTools Heap snapshot 의 root 의 확인
|
|
```javascript
|
|
// Chrome DevTools → Memory → Heap snapshot
|
|
// 매 retainer path 의 (GC root) 까지 추적
|
|
// 매 closure / detached DOM / event listener 의 leak 의 발견
|
|
|
|
// 매 typical leak pattern
|
|
let leakedRef;
|
|
window.addEventListener('click', () => {
|
|
leakedRef = bigData; // 매 GC root (global) 까지 retained
|
|
});
|
|
```
|
|
|
|
### 매 WeakRef 의 reachability 의 우회
|
|
```javascript
|
|
// 매 weak reference — 매 reachability 의 contribute X
|
|
const cache = new Map();
|
|
function set(key, val) {
|
|
cache.set(key, new WeakRef(val)); // 매 GC 의 collect 가능
|
|
}
|
|
function get(key) {
|
|
return cache.get(key)?.deref(); // 매 collected 시 undefined
|
|
}
|
|
```
|
|
|
|
### 매 FinalizationRegistry 의 cleanup hook
|
|
```javascript
|
|
const registry = new FinalizationRegistry((heldValue) => {
|
|
console.log('Object collected:', heldValue);
|
|
externalResources.delete(heldValue);
|
|
});
|
|
|
|
function trackResource(obj, id) {
|
|
registry.register(obj, id);
|
|
}
|
|
// 매 obj 의 unreachable 시 cleanup 의 trigger
|
|
```
|
|
|
|
### 매 v8 의 heap snapshot 의 programmatic
|
|
```javascript
|
|
import v8 from 'node:v8';
|
|
import fs from 'node:fs';
|
|
|
|
const snapshot = v8.getHeapSnapshot();
|
|
snapshot.pipe(fs.createWriteStream('heap.heapsnapshot'));
|
|
// 매 Chrome DevTools 의 import → reachability graph 의 분석
|
|
```
|
|
|
|
### 매 Cycle 의 detection
|
|
```javascript
|
|
// 매 Refcount 의 약점 — 매 cycle 의 leak
|
|
let a = {}, b = {};
|
|
a.ref = b;
|
|
b.ref = a;
|
|
// 매 V8 의 reachability-based GC 의 cycle 의 collect (root 의 unreachable 시)
|
|
```
|
|
|
|
## 매 결정 기준
|
|
| 상황 | Approach |
|
|
|---|---|
|
|
| 일반 object | implicit reachability — 매 default |
|
|
| Cache | WeakRef + FinalizationRegistry |
|
|
| External resource | FinalizationRegistry 의 cleanup |
|
|
| Cycle 의심 | heap snapshot 의 retainer path |
|
|
| Memory leak debug | DevTools Memory tab |
|
|
|
|
**기본값**: 매 explicit ref 의 nullify 보다 매 scope 의 의도된 사용 의 reachability 의 자연스러운 종료.
|
|
|
|
## 🔗 Graph
|
|
- 부모: [[Garbage Collection]] · [[Mark-Sweep-Compact 알고리즘]]
|
|
- 변형: [[Incremental Marking]] · [[Tri-color Marking]]
|
|
- 응용: [[GC Root]] · [[Memory Leak Debugging]]
|
|
- Adjacent: [[Generational Hypothesis]] · [[Write Barrier]]
|
|
|
|
## 🤖 LLM 활용
|
|
**언제**: GC 동작 의 explain, memory leak 의 diagnose, WeakRef vs Map 의 권장.
|
|
**언제 X**: 매 application 의 GC 의 strict timing 의 의존 의 답변 — 매 non-deterministic 임 의 인지.
|
|
|
|
## ❌ 안티패턴
|
|
- **Global cache**: 매 unbounded Map 의 GC root 까지 retained — 매 WeakMap 의 사용.
|
|
- **Closure leak**: 매 outer function 의 large var 의 inner closure 의 capture.
|
|
- **Detached DOM**: 매 removed node 의 JS reference 의 retained — 매 listener cleanup.
|
|
|
|
## 🧪 검증 / 중복
|
|
- Verified (V8 docs, Garbage Collection Handbook by Jones).
|
|
- 신뢰도 A.
|
|
|
|
## 🕓 Changelog
|
|
| 날짜 | 변경 |
|
|
|---|---|
|
|
| 2026-05-08 | Phase 1 |
|
|
| 2026-05-10 | Manual cleanup — Reachability analysis FULL 작성 |
|