"매 64-bit 시스템 위에서 heap pointer를 32-bit 로 줄여 절반 공간으로 저장". 매 V8(2020), Hermes, JVM(CompressedOops, 2008부터) 의 heap memory ~40% 절감 + 매 cache locality 향상. 매 4GB 안 heap 제한 대신 매 typical web app 에는 충분.
매 핵심
매 동기
매 64-bit OS 의 V8 heap object 의 80% 가 pointer field 차지.
매 pointer = 매 8 bytes 인데 실제 정보 entropy ~32 bits (heap < 4GB).
매 절반으로 → 매 RAM↓, 매 GC scan 시간 ↓, 매 L1/L2 cache hit ↑.
매 V8 scheme (post-2020)
Cage: 매 4GB 정렬된 가상 메모리 reservation.
Base register / R13: 매 cage base 주소 보관 (cached).
32-bit slot: 매 cage 안 offset.
Smi tagging: 매 31-bit integer 의 inline (1 LSB tag).
Decompress: addr = base + (int64_t)(int32_t)compressed.
매 trade-off
+ Heap mem ~30–43% 절감, 매 V8 startup ↓.
+ Cache pressure ↓ → 매 throughput 5-10% ↑.
− Per-access decompression cost (매 작음, 보통 +1 ALU).
− Heap 4GB 한계 (매 큰 app 의 큰 process 분할 필요).
− External pointer 는 sandboxed pointer table 로 indirection 추가.
매 비슷한 system
JVM CompressedOops: 매 8-byte aligned + shift → 매 32GB heap 까지 32-bit.
CHERI capabilities: 매 다른 방향 — 매 capability + bounds 로 fat pointer.
Hermes (RN): 매 32-bit pointer + handle table.
WebAssembly memory64 vs memory32: 매 동일 motif.
💻 패턴
Compress / decompress (V8 conceptual)
// 매 V8 cage base = 4GB-aligned
inlineAddressDecompress(uint32_tcompressed,Addresscage_base){returncage_base+static_cast<int64_t>(static_cast<int32_t>(compressed));}inlineuint32_tCompress(Addressfull){returnstatic_cast<uint32_t>(full);// 매 lower 32 bits
}// 매 Smi (Small Integer) tagging
constexprintkSmiTagSize=1;inlineboolIsSmi(uint32_tv){return(v&1)==0;}inlineint32_tSmiValue(uint32_tv){returnstatic_cast<int32_t>(v)>>1;}
Tagged slot in heap object
classHeapObject{uint32_tmap_;// 매 type info, compressed
uint32_tproperties_;// 매 compressed
uint32_telements_;// 매 compressed
// 매 instance fields follow, all 4 bytes each
};// 매 compare: 64-bit pointer system 에서 same object = 24 bytes header
JVM CompressedOops
# 매 default ON when heap ≤ 32GB on 64-bit JVM
java -XX:+UseCompressedOops -Xmx16g App
# 매 8-byte alignment + 3-bit shift → 매 32-bit reference 가 32GB 까지 cover
java -XX:ObjectAlignmentInBytes=8 ...
Sandboxed external pointers (V8 2024+)
// 매 untrusted external ptr → 매 indirection table
classExternalPointerTable{Addressentries_[N];public:uint32_tAllocate(Addressexternal){uint32_thandle=next_++;entries_[handle]=external;returnhandle;// 매 store handle 32-bit, not raw ptr
}AddressResolve(uint32_thandle){returnentries_[handle];}};
Disable pointer compression (V8 build)
# 매 large heap (>4GB) needed
gn args out.gn/x64.release
# v8_enable_pointer_compression = false
ninja -C out.gn/x64.release v8
Hermes 32-bit handle (React Native)
// 매 HermesValue = 64-bit NaN-boxed; pointer 부분은 cage offset 32-bit
structHermesValue{uint64_traw;boolisPointer()const{return(raw&kTagMask)==kPointerTag;}HeapPtrgetPointer()const{returnbase_+(raw&kPayloadMask);}};
매 결정 기준
상황
Approach
Browser tab / Node ≤ 4GB
V8 pointer compression ON (default)
Large server-side V8 (>4GB)
Compile with compression OFF or use isolates
JVM ≤ 32GB heap
CompressedOops ON (default)
JVM > 32GB
UseCompressedOops auto-OFF
Mobile JS (Hermes)
Always 32-bit handle
Custom GC engine
매 cage allocator + tagged 4-byte slot 직접 구현
기본값: 매 modern engine 의 default ON; 매 disable 은 명백한 large-heap 이유 있을 때만.