f8b21af4be
10_Wiki/Topics 대규모 정리: - 오류 캡처/미완성 stub 문서 227개 제거 - 교차폴더 중복 43클러스터 병합 (63파일 → redirect) - 링크명 정규화: 깨진 링크 수정·redirect 직결·개념 매핑 ~2,400건 - 카테고리 MOC 6개 신규 생성 - Graph 섹션 미해결 related-keyword 링크 10,058건 제거 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
178 lines
5.4 KiB
Markdown
178 lines
5.4 KiB
Markdown
---
|
|
id: wiki-2026-0508-마크-스윕-mark-sweep
|
|
title: 마크 스윕(Mark Sweep)
|
|
category: 10_Wiki/Topics
|
|
status: verified
|
|
canonical_id: self
|
|
aliases: [Mark-Sweep, Mark and Sweep, Tracing GC]
|
|
duplicate_of: none
|
|
source_trust_level: A
|
|
confidence_score: 0.9
|
|
verification_status: applied
|
|
tags: [gc, memory, runtime, algorithm, jvm, v8]
|
|
raw_sources: []
|
|
last_reinforced: 2026-05-10
|
|
github_commit: pending
|
|
tech_stack:
|
|
language: C/C++/Java
|
|
framework: JVM/V8/Go runtime
|
|
---
|
|
|
|
# 마크 스윕(Mark Sweep)
|
|
|
|
## 매 한 줄
|
|
> **"매 root 에서 reachable 한 것만 매 mark, 매 unmarked 는 매 sweep"**. 매 1960 McCarthy 의 LISP 가 매 origin, 매 60+ 년 동안 매 tracing GC 의 backbone. 매 modern 변형 (G1, ZGC, Shenandoah, V8 Orinoco) 매 모두 매 mark-sweep 의 evolution.
|
|
|
|
## 매 핵심
|
|
|
|
### 매 두 phase
|
|
1. **매 Mark**: 매 root (stack, register, global) 에서 매 reachable graph 매 traverse, 매 mark bit 설정.
|
|
2. **매 Sweep**: 매 heap 전체를 매 scan, 매 unmarked block 을 매 free list 로.
|
|
|
|
### 매 vs 친척들
|
|
- **매 vs Reference Counting**: 매 cycle 처리 가능, 매 thoughput ↑, 매 latency spike ↑.
|
|
- **매 vs Copying (Cheney)**: 매 fragmentation 발생, 매 메모리 효율 ↑ (매 copy 가 1/2 reserve X).
|
|
- **매 vs Mark-Compact**: 매 sweep 후 compact 추가 — 매 fragmentation 해결.
|
|
|
|
### 매 Tri-color abstraction
|
|
- **매 White**: 매 unvisited (sweep 대상).
|
|
- **매 Grey**: 매 reachable, 매 children 미 traverse.
|
|
- **매 Black**: 매 reachable + 매 children traversed.
|
|
- 매 invariant: 매 black → white edge 의 X (매 보장 시 concurrent OK).
|
|
|
|
### 매 Modern 변형
|
|
- 매 Generational: 매 young/old, 매 minor/major GC.
|
|
- 매 Concurrent: 매 mark 를 매 mutator 와 병행.
|
|
- 매 Incremental: 매 small chunk 씩 매 stop.
|
|
- 매 Region-based (G1): 매 heap 을 region 으로 split.
|
|
|
|
## 패턴
|
|
|
|
### Naive mark
|
|
```c
|
|
typedef struct Obj {
|
|
uint8_t marked;
|
|
size_t n_refs;
|
|
struct Obj** refs;
|
|
} Obj;
|
|
|
|
void mark(Obj* o) {
|
|
if (!o || o->marked) return;
|
|
o->marked = 1;
|
|
for (size_t i = 0; i < o->n_refs; i++) mark(o->refs[i]);
|
|
}
|
|
```
|
|
|
|
### Sweep over heap
|
|
```c
|
|
typedef struct Heap { Obj* objects[MAX]; size_t n; Obj* free_list; } Heap;
|
|
|
|
void sweep(Heap* h) {
|
|
Obj* fl = NULL;
|
|
for (size_t i = 0; i < h->n; i++) {
|
|
Obj* o = h->objects[i];
|
|
if (!o) continue;
|
|
if (o->marked) {
|
|
o->marked = 0; // 매 reset for next cycle
|
|
} else {
|
|
// 매 free
|
|
o->refs[0] = (Obj*)fl; // 매 link to free list
|
|
fl = o;
|
|
h->objects[i] = NULL;
|
|
}
|
|
}
|
|
h->free_list = fl;
|
|
}
|
|
```
|
|
|
|
### Tri-color (worklist)
|
|
```c
|
|
void mark_tricolor(Obj* roots[], size_t n) {
|
|
Queue grey;
|
|
for (size_t i = 0; i < n; i++) { roots[i]->color = GREY; enqueue(&grey, roots[i]); }
|
|
while (!empty(&grey)) {
|
|
Obj* o = dequeue(&grey);
|
|
for (size_t i = 0; i < o->n_refs; i++) {
|
|
Obj* c = o->refs[i];
|
|
if (c && c->color == WHITE) { c->color = GREY; enqueue(&grey, c); }
|
|
}
|
|
o->color = BLACK;
|
|
}
|
|
}
|
|
```
|
|
|
|
### Write barrier (concurrent invariant)
|
|
```c
|
|
// 매 Dijkstra-style: 매 black 이 white 를 가리키지 않도록
|
|
void write_barrier(Obj* parent, size_t i, Obj* child) {
|
|
if (parent->color == BLACK && child && child->color == WHITE) {
|
|
child->color = GREY;
|
|
enqueue(&grey, child);
|
|
}
|
|
parent->refs[i] = child;
|
|
}
|
|
```
|
|
|
|
### Generational hook (write barrier on old → young)
|
|
```c
|
|
// 매 remembered set 에 매 old object 추가
|
|
void gen_write_barrier(Obj* parent, size_t i, Obj* child) {
|
|
parent->refs[i] = child;
|
|
if (parent->gen == OLD && child && child->gen == YOUNG)
|
|
remembered_set_add(parent);
|
|
}
|
|
```
|
|
|
|
### JVM tuning (G1)
|
|
```bash
|
|
java -XX:+UseG1GC \
|
|
-XX:MaxGCPauseMillis=100 \
|
|
-XX:G1HeapRegionSize=16m \
|
|
-Xms4g -Xmx4g \
|
|
-Xlog:gc*:file=gc.log \
|
|
-jar app.jar
|
|
```
|
|
|
|
### V8 incremental marking trace
|
|
```bash
|
|
node --trace-gc --trace-gc-verbose --max-old-space-size=4096 app.js
|
|
```
|
|
|
|
## 매 결정 기준
|
|
| 상황 | GC |
|
|
|---|---|
|
|
| 매 simple, 매 single-thread | Mark-Sweep |
|
|
| 매 fragmentation 의 우려 | Mark-Compact |
|
|
| 매 short-lived dominant | Generational + copying young |
|
|
| 매 latency-critical (<10ms) | ZGC / Shenandoah |
|
|
| 매 throughput-critical | Parallel/Throughput GC |
|
|
| 매 ref-cycle 매 잦음 | Tracing GC (RC X) |
|
|
|
|
**기본값**: 매 JVM 8GB 초과 = 매 G1 (default), 매 latency 절실 = 매 ZGC.
|
|
|
|
## Graph
|
|
- 부모: [[Garbage Collection]] · [[Memory Management]]
|
|
- 응용: [[JVM]] · [[V8]]
|
|
- Adjacent: [[Tri-color Marking]] · [[Write Barrier]] · [[Reference Counting]]
|
|
|
|
## LLM 활용
|
|
**언제**: 매 GC 알고리즘 설명, 매 JVM/V8 tuning, 매 GC log 분석, 매 toy GC 작성.
|
|
**언제 X**: 매 production 의 직접 GC patch (매 risk ↑) — 매 review 만.
|
|
|
|
## 안티패턴
|
|
- **매 Frequent full GC trigger**: 매 -Xmx 부족 / 매 leak.
|
|
- **매 No write barrier in concurrent**: 매 missed object 의 free.
|
|
- **매 Recursive mark on deep graph**: 매 stack overflow — 매 worklist 사용.
|
|
- **매 Tuning without log**: 매 -Xlog:gc* / -verbose:gc 매 필수.
|
|
- **매 Force System.gc()**: 매 hint, 매 흔히 매 worse latency.
|
|
|
|
## 검증 / 중복
|
|
- Verified: Jones/Hosking/Moss "The Garbage Collection Handbook", JVM HotSpot docs, V8 blog (Orinoco), Go runtime docs.
|
|
- 신뢰도 A.
|
|
|
|
## Changelog
|
|
| 날짜 | 변경 |
|
|
|---|---|
|
|
| 2026-05-08 | Phase 1 |
|
|
| 2026-05-10 | Manual cleanup — mark-sweep tri-color/write barrier/tuning 작성 |
|