7.4 KiB
7.4 KiB
id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
| id | title | category | status | source_trust_level | verification_status | created_at | updated_at | tags | tech_stack | applied_in | aliases | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| cs-memory-management-patterns | Memory Management — GC / arena / RC / ownership | Coding | draft | B | conceptual | 2026-05-09 | 2026-05-09 |
|
|
|
Memory Management Patterns
Memory 의 알고리즘. GC, arena, ref count, ownership (Rust).
📖 핵심 개념
- Stack vs heap.
- Manual free vs auto.
- GC (mark-sweep, generational).
- RC (auto, cycle).
- Ownership (Rust).
💻 코드 패턴
Stack vs heap
Stack:
- Function call frame.
- LIFO.
- 빠름.
- 작은 (1-8 MB).
Heap:
- 동적 alloc.
- 큰.
- Free 필요 (manual or GC).
C / C++ manual
int* arr = malloc(100 * sizeof(int));
// 사용.
free(arr);
→ Forget = leak. Double-free = crash.
C++ RAII
{
std::vector<int> v(100);
// 사용.
} // 자동 destroy (RAII).
→ Scope 끝 = destructor.
Smart pointer (C++)
auto p = std::make_unique<MyClass>(); // exclusive.
auto s = std::make_shared<MyClass>(); // shared (RC).
auto w = std::weak_ptr<MyClass>(s); // non-owning.
→ unique = single owner. shared = ref count. weak = no own (cycle 방지).
Rust ownership
let s = String::from('hello');
let s2 = s; // moved.
// println!('{}', s); // ❌ s 가 moved.
fn take(s: String) {}
take(s2); // moved.
// println!('{}', s2); // ❌
→ Compile-time. No GC.
Rust borrow
fn borrow(s: &String) {
println!('{}', s);
}
let s = String::from('hello');
borrow(&s);
println!('{}', s); // OK — borrow 끝.
→ Read borrow (multiple). Write borrow (exclusive).
Rust Arc / Rc
use std::rc::Rc;
let a = Rc::new(MyData);
let b = a.clone(); // count = 2.
// Drop = count--.
→ Single-threaded.
use std::sync::Arc;
let a = Arc::new(MyData);
let b = a.clone(); // atomic count.
→ Multi-thread.
Garbage Collection (GC)
Mark-Sweep:
- Reachable 인 root → mark.
- Unmarked = free.
- Stop-the-world.
Generational:
- Young / old generation.
- Young 가 자주 GC (대부분 die).
- Old 가 가끔.
Concurrent (Java G1, ZGC):
- Application + 동시.
- Pause time ↓.
Java GC tuning
java -XX:+UseG1GC -Xmx4g -Xms4g app.jar
java -XX:+UseZGC -Xmx16g app.jar # large heap, low pause.
Go GC
Concurrent + tri-color mark.
- 1 ms pause typical.
- 자체 tune 안 됨.
- GOGC env var.
GOGC=200 # GC 가 less frequent (memory ↑).
Python ref count + GC
Ref count + cycle detector.
- 매 object 가 count.
- Count 0 = free.
- Cycle = generational GC.
import sys
sys.getrefcount(obj)
JS GC (V8)
Generational + concurrent mark-sweep.
- 매 minor GC = young (frequent).
- Major GC = old (rare).
- Tuning = generally 안 함.
→ Memory leak 가 흔함 (closure, listener).
Memory leak in JS
// ❌ Closure 가 외부 변수 retain
function setup() {
const big = new Array(1000000);
return () => console.log('hi'); // big 도 retain.
}
const fn = setup();
// big 가 GC 안.
// ❌ Event listener
window.addEventListener('resize', handler);
// handler 가 ref. Forever.
// ✅
window.addEventListener('resize', handler, { signal: ac.signal });
ac.abort();
Arena allocation
모든 alloc 가 1 arena.
Arena reset 시 모든 free.
→ Game / web request frame.
- 매 frame / request 의 arena.
- Reset = O(1).
use bumpalo::Bump;
let arena = Bump::new();
let v = arena.alloc(MyData { ... });
// ... 매 frame 의 alloc.
// 매 frame 끝:
drop(arena); // 모든 free.
→ Game engine 친화.
Pool allocation
struct Pool<T> {
items: Vec<T>,
free: Vec<usize>,
}
impl<T> Pool<T> {
fn alloc(&mut self, item: T) -> usize {
if let Some(idx) = self.free.pop() {
self.items[idx] = item;
idx
} else {
self.items.push(item);
self.items.len() - 1
}
}
fn free(&mut self, idx: usize) {
self.free.push(idx);
}
}
→ 같은 size object 의 fast alloc / free.
Reference cycle
class Node {
constructor(public next?: Node) {}
}
const a = new Node();
const b = new Node();
a.next = b;
b.next = a; // cycle.
// JS GC 가 detect (mark-sweep).
// 옛 ref count 만 = leak.
→ Modern GC 가 cycle 처리.
WeakRef / WeakMap (JS)
const cache = new WeakMap<object, string>();
cache.set(user, 'cached value');
// User 가 GC 됨 = cache entry 도.
→ Memory leak 방지.
iOS / macOS ARC
class Person {
var partner: Person?
}
let alice = Person()
let bob = Person()
alice.partner = bob // strong.
bob.partner = alice // strong → cycle.
// → Memory leak.
class Person {
weak var partner: Person? // weak — no retain.
}
Android Java/Kotlin
// Static reference 가 Activity:
object MyManager {
var activity: Activity? = null
}
// Activity rotate = leak (옛 instance retained).
// 해결: WeakReference.
object MyManager {
var activity: WeakReference<Activity>? = null
}
Memory profiler
- Chrome DevTools (JS).
- Xcode Instruments (iOS).
- Android Studio Profiler.
- Java VisualVM / async-profiler.
- Go pprof.
- Rust valgrind / heaptrack.
→ Leak 발견.
Production memory
- Heap size limit (container OOM).
- 매 user 별 budget.
- GC pause 가 latency.
- Memory pressure handling.
→ Native_Memory_Pressure_iOS_Android.
Rust 의 zero-cost
Compile-time check.
- Runtime overhead 0.
- Manual 보다 더 안전.
→ "Safety + performance" 의 답.
When GC?
Pros:
- 매 dev 가 memory worry X.
- Rapid development.
- Cycle 자동.
Cons:
- Pause time.
- Memory usage 큰 (overhead).
- Predictability ↓ (real-time 안).
→ Most app = GC OK.
Game / embedded / OS = manual / Rust.
Hybrid (Rust + GC language)
LLM agent:
- Rust 의 fast core (vector search).
- Python 의 logic (script).
→ Best of both.
Memory layout
SOA (Struct of Arrays):
- 매 field 의 array.
- Cache locality 가 좋음 (1 field 만 read).
AOS (Array of Structs):
- 매 struct 의 array.
- 매 row 사용 시 좋음.
→ Use case 따라.
NUMA
Multi-socket server.
- 매 socket 의 own memory.
- Cross-socket 가 slow.
→ NUMA-aware allocation.
Memory mapped file (mmap)
int fd = open('big-file', O_RDONLY);
char* data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
// File 가 memory 처럼.
// OS 가 page (lazy).
→ 큰 file 처리.
🤔 의사결정 기준
| Language | Memory |
|---|---|
| Rust | Ownership (compile-time) |
| C++ | RAII + smart pointer |
| Go | GC (concurrent) |
| Java | G1 / ZGC |
| Python | RC + cycle |
| JS | V8 GC |
| Swift | ARC + weak |
| Kotlin | JVM GC |
❌ 안티패턴
- Manual free 잊음: leak.
- Cycle 의 ARC: leak.
- Static reference 의 Activity: leak.
- Closure 의 big object: leak.
- GC tune 0 인지: pause.
- Rust 가 Arc 가짜: cycle = leak.
🤖 LLM 활용 힌트
- Rust ownership 가 modern.
- GC 가 most app 의 OK.
- Cycle 의 ARC / RC = weak.
- Leak 가 흔한 (closure, listener, static).