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>
143 lines
4.8 KiB
Markdown
143 lines
4.8 KiB
Markdown
---
|
|
id: wiki-20260508-write-barrier-redir
|
|
title: Write Barrier
|
|
category: 10_Wiki/Topics
|
|
status: verified
|
|
canonical_id: self
|
|
aliases: [쓰기 장벽, GC Write Barrier, Generational Barrier]
|
|
duplicate_of: none
|
|
source_trust_level: A
|
|
confidence_score: 0.9
|
|
verification_status: applied
|
|
tags: [garbage-collection, runtime, v8, jvm, performance]
|
|
raw_sources: []
|
|
last_reinforced: 2026-05-10
|
|
github_commit: pending
|
|
tech_stack:
|
|
language: cpp
|
|
framework: v8, jvm
|
|
---
|
|
|
|
# Write Barrier
|
|
|
|
## 매 한 줄
|
|
> **"매 inter-generational pointer 의 tracking 의 cost"**. Write barrier 는 매 generational / incremental GC 가 매 old-gen object 의 reference 가 매 young-gen 의 가리킬 때 매 remembered set 의 update 의 small code snippet. 매 V8 / JVM / .NET 의 모든 modern GC 의 essential primitive — 매 minor GC 가 매 entire old-gen 의 scan 의 회피.
|
|
|
|
## 매 핵심
|
|
|
|
### 매 why
|
|
- **Generational hypothesis**: 매 most objects die young → young-gen 만 frequent collect.
|
|
- **Inter-gen pointer 의 problem**: 매 minor GC 의 root 로 매 stack + old→young pointer 의 필요.
|
|
- **Naive: scan all old-gen** → expensive.
|
|
- **Solution**: 매 write 마다 (old.field = young) 매 barrier 의 firing → remembered set 의 add.
|
|
|
|
### 매 type
|
|
- **Snapshot-at-the-Beginning (SATB)**: 매 incremental marking 의 use (G1, ZGC, V8 Orinoco). 매 overwritten old reference 의 record.
|
|
- **Incremental Update**: 매 new reference 의 record (CMS).
|
|
- **Card marking**: 매 old-gen 의 fixed-size card (e.g., 512B) 의 dirty bit 의 mark — coarse but cheap.
|
|
|
|
### 매 cost
|
|
- 매 store 마다 ~3-5 instruction overhead.
|
|
- 매 hot-loop 의 store 의 bottleneck 가능 — 매 elision optimization 의 important.
|
|
|
|
## 💻 패턴
|
|
|
|
### 1. Card-marking pseudo-implementation
|
|
```cpp
|
|
// 매 1MB heap 의 512B card → 2048 cards
|
|
const size_t CARD_SIZE = 512;
|
|
uint8_t card_table[HEAP_SIZE / CARD_SIZE];
|
|
|
|
inline void write_barrier(Object* obj, Object** field, Object* new_val) {
|
|
*field = new_val;
|
|
if (in_old_gen(obj) && in_young_gen(new_val)) {
|
|
size_t card = ((uintptr_t)field - heap_base) / CARD_SIZE;
|
|
card_table[card] = 1; // dirty
|
|
}
|
|
}
|
|
|
|
void minor_gc_scan() {
|
|
for (size_t i = 0; i < num_cards; i++) {
|
|
if (card_table[i]) {
|
|
scan_card_for_young_refs(i);
|
|
card_table[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2. V8-style incremental marking barrier (simplified)
|
|
```cpp
|
|
// 매 SATB: overwritten reference 의 mark gray
|
|
inline void v8_write_barrier(HeapObject* host, Object** slot, Object* value) {
|
|
Object* old = *slot;
|
|
*slot = value;
|
|
if (incremental_marking_active && is_white(old)) {
|
|
mark_gray(old); // 매 not-yet-marked 의 reference 의 처리 보장
|
|
}
|
|
// 매 generational: old→young 의 record
|
|
if (host->in_old_space() && value->in_young_space()) {
|
|
remembered_set.insert(slot);
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3. JIT-emitted barrier elision
|
|
```cpp
|
|
// 매 compiler 의 barrier 의 omit 가능 case:
|
|
// 1. 매 store 의 target 이 fresh allocation (young → ?)
|
|
// 2. 매 store value 의 primitive (int, double)
|
|
// 3. 매 immutable field 의 init store
|
|
function emitStore(host, field, value) {
|
|
if (isFreshlyAllocated(host)) emitRawStore(host, field, value);
|
|
else emitBarrieredStore(host, field, value);
|
|
}
|
|
```
|
|
|
|
### 4. Measure barrier overhead (benchmark)
|
|
```typescript
|
|
// Node.js / V8 의 barrier overhead 의 indirect measure
|
|
const N = 1e7;
|
|
const arr = new Array(N);
|
|
const obj = { ref: null };
|
|
console.time('store-loop');
|
|
for (let i = 0; i < N; i++) obj.ref = arr; // 매 barrier 의 fire
|
|
console.timeEnd('store-loop');
|
|
```
|
|
|
|
## 매 결정 기준
|
|
| 상황 | Approach |
|
|
|---|---|
|
|
| 매 hot inner loop 의 store | primitive 의 use, object reference 의 회피 |
|
|
| 매 immutable struct | barrier-free design |
|
|
| 매 large old-gen | card marking 의 prefer |
|
|
| 매 incremental GC | SATB barrier 의 use |
|
|
| 매 low-latency (ZGC) | colored pointers + load barrier 의 alternative |
|
|
|
|
**기본값**: 매 application code 의 barrier 의 invisible — 매 GC 의 implementation detail.
|
|
|
|
## 🔗 Graph
|
|
- 부모: [[Garbage Collection]] · [[Memory Management]]
|
|
- 변형: [[Card Marking]]
|
|
- 응용: [[Incremental GC]] · [[Orinoco]]
|
|
- Adjacent: [[Mark Sweep Compact]] · [[Garbage Collection|Generational Hypothesis]]
|
|
|
|
## 🤖 LLM 활용
|
|
**언제**: GC internals 의 understanding, runtime tuning, performance 의 explain.
|
|
**언제 X**: Rust / non-GC language (no barrier), reference counting (no generational).
|
|
|
|
## ❌ 안티패턴
|
|
- **Barrier elision 의 manual attempt 의 application code**: 매 unsafe.
|
|
- **Excessive store-to-old-gen 의 hot path**: 매 remembered set 의 explosion.
|
|
- **Ignoring barrier cost 의 high-frequency mutation**: 매 hidden bottleneck.
|
|
|
|
## 🧪 검증 / 중복
|
|
- Verified (Jones GC handbook 2011, V8 Orinoco docs, JVM HotSpot source).
|
|
- 신뢰도 A.
|
|
|
|
## 🕓 Changelog
|
|
| 날짜 | 변경 |
|
|
|---|---|
|
|
| 2026-05-08 | Phase 1 |
|
|
| 2026-05-10 | Manual cleanup — write barrier 의 type, cost, V8 example 의 expand |
|