148 lines
5.1 KiB
Markdown
148 lines
5.1 KiB
Markdown
---
|
||
id: wiki-20260508-pointer-compression-redir
|
||
title: Pointer Compression
|
||
category: 10_Wiki/Topics
|
||
status: verified
|
||
canonical_id: self
|
||
aliases: [pointer-compression, V8 pointer compression, 32-bit pointer]
|
||
duplicate_of: none
|
||
source_trust_level: A
|
||
confidence_score: 0.92
|
||
verification_status: applied
|
||
tags: [v8, memory, gc, optimization, runtime]
|
||
raw_sources: []
|
||
last_reinforced: 2026-05-10
|
||
github_commit: pending
|
||
tech_stack:
|
||
language: JavaScript/C++
|
||
framework: V8
|
||
---
|
||
|
||
# Pointer Compression
|
||
|
||
## 매 한 줄
|
||
> **"매 64-bit pointer를 32-bit offset으로 packing해서 heap memory를 거의 반으로 줄임"**. V8 v8.0 (2020) 부터 default — heap base register + 32-bit compressed pointer 의 조합. 매 modern 2026 V8 (Node 22, Chrome 120+)에서 매 표준 동작.
|
||
|
||
## 매 핵심
|
||
|
||
### 매 동작 원리
|
||
- 매 4GB heap 안의 모든 object 의 32-bit offset 으로 표현 — base pointer 1개만 64-bit, 나머지는 32-bit.
|
||
- 매 Tagged pointer scheme: 매 LSB 1 bit 의 SMI (Small Integer) vs HeapObject 구분 의 사용.
|
||
- 매 decompression: `real_addr = base + (compressed << 1)` — 매 single ALU op.
|
||
- 매 compression: 매 store 시 `(real_addr - base) >> 1` 의 자동 계산.
|
||
|
||
### 매 trade-off
|
||
- 매 heap size limit: 매 single isolate 의 4GB cap — 매 worker / cluster 의 우회.
|
||
- 매 CPU overhead: 매 매 dereference 의 add 1 instruction — 매 ~3% slower.
|
||
- 매 memory savings: 매 typical Node heap 의 30-43% 감소 — 매 pointer-heavy workload 의 클수록 효과 큼.
|
||
|
||
### 매 응용
|
||
1. Chrome tab 의 RAM 의 ~10% 감소 — 매 tab 수십 개 의 환경.
|
||
2. Node.js process 의 startup memory 의 약 200MB→130MB.
|
||
3. Edge / serverless 의 cold start 의 RSS reduction.
|
||
|
||
## 💻 패턴
|
||
|
||
### 매 Compressed pointer 구조 의 이해
|
||
```cpp
|
||
// V8 internal — Tagged<Object> representation
|
||
class Tagged {
|
||
uint32_t ptr_; // 32-bit compressed pointer (was 64-bit)
|
||
|
||
// Decompress on access
|
||
Address decompress(Address base) const {
|
||
return base + (ptr_ & ~kSmiTagMask);
|
||
}
|
||
};
|
||
```
|
||
|
||
### 매 Heap base register 의 활용
|
||
```cpp
|
||
// Generated machine code (x86_64)
|
||
// Before: mov rax, [rbx+0x8] ; 8 bytes load
|
||
// After: mov eax, [rbx+0x8] ; 4 bytes load
|
||
// add rax, r13 ; r13 holds heap base
|
||
```
|
||
|
||
### 매 Node 의 heap 의 4GB cap 우회
|
||
```javascript
|
||
// 매 single isolate 의 4GB 제한 — worker thread 의 분리
|
||
import { Worker } from 'node:worker_threads';
|
||
|
||
// 매 각 worker 의 own isolate (own 4GB heap)
|
||
const workers = Array.from({ length: 4 }, () =>
|
||
new Worker('./heavy-task.js')
|
||
);
|
||
// 총 16GB heap usage 가능 (4GB × 4 isolates)
|
||
```
|
||
|
||
### 매 SMI (Small Integer) 활용
|
||
```javascript
|
||
// 매 V8 의 SMI optimization — 31-bit int 의 boxing 없이 tagged pointer 안에 직접
|
||
const x = 42; // 매 SMI — 매 heap 할당 X
|
||
const y = 2**32; // 매 HeapNumber — 매 heap allocation
|
||
// 매 SMI 의 GC pressure 의 감소 효과
|
||
```
|
||
|
||
### 매 Pointer compression 의 disable (rare)
|
||
```bash
|
||
# 매 Node build flag — 매 4GB heap 초과 필요 시
|
||
node --no-pointer-compression server.js
|
||
# 매 large in-memory cache (>4GB) 의 use case
|
||
```
|
||
|
||
### 매 Heap 측정
|
||
```javascript
|
||
import v8 from 'node:v8';
|
||
|
||
const stats = v8.getHeapStatistics();
|
||
console.log({
|
||
total: stats.total_heap_size / 1e6, // MB
|
||
limit: stats.heap_size_limit / 1e6, // 매 ~4GB 의 cap
|
||
external: stats.external_memory / 1e6,
|
||
});
|
||
// 매 pointer compression 의 enabled 의 limit 의 4GB 근처
|
||
```
|
||
|
||
### 매 SharedArrayBuffer 의 outside-heap 활용
|
||
```javascript
|
||
// 매 4GB cap 의 우회 — 매 binary data 의 SAB 의 사용
|
||
const sab = new SharedArrayBuffer(8 * 1024 * 1024 * 1024); // 8GB
|
||
// 매 SAB 의 V8 heap 의 외부 allocation — 매 limit 의 영향 X
|
||
```
|
||
|
||
## 매 결정 기준
|
||
| 상황 | Approach |
|
||
|---|---|
|
||
| 일반 Node 앱 | default ON (compression enabled) |
|
||
| Heap > 4GB 필요 | --no-pointer-compression OR worker split |
|
||
| 대용량 binary | SharedArrayBuffer / Buffer (off-heap) |
|
||
| Memory-constrained | default 의 유지 — 매 30%+ saving |
|
||
|
||
**기본값**: pointer compression의 ON 의 유지. 매 4GB cap 의 hit 시 worker thread 의 split.
|
||
|
||
## 🔗 Graph
|
||
- 부모: [[V8 Engine]] · [[Garbage Collection]]
|
||
- 변형: [[Tagged Pointer]] · [[SMI Small Integer]]
|
||
- 응용: [[Nodejs 메모리 최적화]] · [[V8 엔진 힙 아키텍처 및 로그 분석]]
|
||
- Adjacent: [[Old Space]] · [[Mark-Sweep-Compact 알고리즘]]
|
||
|
||
## 🤖 LLM 활용
|
||
**언제**: V8 heap memory 의 분석, Node.js 의 RSS 의 unexpected size 의 explain, 4GB OOM 의 debug.
|
||
**언제 X**: 매 user 의 application code 의 직접 영향 X — 매 V8 internal optimization 임 의 인지.
|
||
|
||
## ❌ 안티패턴
|
||
- **Disable 의 무분별**: `--no-pointer-compression` 의 default 의 사용 — 매 30% memory waste.
|
||
- **Single-isolate 의 4GB+**: 매 limit 의 무시 후 OOM — worker split 의 필요.
|
||
- **SMI 의 violation**: 매 hot path 의 large int 의 사용 — 매 HeapNumber boxing 의 GC pressure.
|
||
|
||
## 🧪 검증 / 중복
|
||
- Verified (V8 blog "Pointer Compression in V8" 2020, Chromium docs).
|
||
- 신뢰도 A.
|
||
|
||
## 🕓 Changelog
|
||
| 날짜 | 변경 |
|
||
|---|---|
|
||
| 2026-05-08 | Phase 1 |
|
||
| 2026-05-10 | Manual cleanup — V8 pointer compression FULL 작성 |
|