Garbage Collection
🔥 1. Tổng Quan về Garbage Collection trong Go
Go là ngôn ngữ có garbage collector (GC) built-in, được thiết kế để:
Tự động quản lý bộ nhớ (không cần
free()
như C/C++).Tối ưu cho latency thấp, không pause quá lâu.
Concurrent, Generational và Non-compacting GC.
Từ Go 1.5 trở đi, GC của Go là Concurrent Mark-and-Sweep, được cải tiến qua từng version.
🧠 2. Cơ chế hoạt động của GC trong Go
Bước 1: Mark Phase (đánh dấu)
Tìm tất cả các object đang được tham chiếu từ root set (global vars, stack vars...).
Sử dụng tracing GC để theo dấu tất cả các object reachable.
Được thực hiện song song với các goroutines.
Bước 2: Sweep Phase
Dọn dẹp các object không còn được đánh dấu (unreachable).
Bộ nhớ được trả về heap và có thể tái sử dụng.
Điểm đặc biệt:
GC không compacting, nghĩa là không dời object trong heap (khác Java).
Có write barrier để hỗ trợ marking trong khi chương trình đang chạy.
⚙️ 3. GC Tuning & Metrics
Go cho phép bạn theo dõi và điều chỉnh GC để phù hợp với use-case:
⚙️ GC Parameters:
SetGCPercent(100)
(default): Khi heap tăng 100% kể từ lần GC trước → trigger GC.SetGCPercent(20)
: Dọn sớm hơn → latency thấp, nhưng CPU tốn hơn.
🔍 GC Metrics:
🛠️ 4. GC Performance Tuning trong Production
Mục tiêu: Tối ưu giữa latency và throughput.
✅ Các chiến lược:
Giảm cấp phát không cần thiết (avoid unnecessary allocations).
Dùng
sync.Pool
cho object reuse.Tránh tạo slice/map tạm thời trong hot path.
Giữ object nhỏ sống lâu trong stack thay vì heap:
GC trong Go không quét stack, nếu object chỉ nằm trong stack → không phải dọn.
Prefetch bộ nhớ (bằng warm-up request).
✅ sync.Pool – một kỹ thuật rất hay:
Lợi ích: Giảm số lượng object GC phải xử lý → giảm áp lực GC.
🔥 5. High-level Concepts (Senior Level)
📌 Write Barrier
GC sử dụng "tri-color" marking: trắng (chưa mark), xám (chưa quét con), đen (quét xong).
Write barrier giúp tránh "lost updates" khi chương trình đang cập nhật object trong lúc GC đang chạy.
📌 GC Safe Points
Điểm mà goroutine có thể safely bị dừng lại để phục vụ GC.
Là lý do tại sao
for {}
mà không gọi hàm nào sẽ không bao giờ trigger GC (nó không có safe point).
📌 Stack Scanning
Go chỉ scan stack khi cần.
Object nằm hoàn toàn trong stack không bị GC dọn, nhưng khi escape ra heap thì phải track.
🧪 6. Thực nghiệm GC – Đo và Debug
Dùng GODEBUG
để bật debug log:
GODEBUG
để bật debug log:Kết quả:
Giải thích:
0.16+1.2+0.016 ms
: Mark start, concurrent mark, mark termination4->4->2 MB
: Heap size before GC, after mark, after sweep5 MB goal
: Target heap size to next GC8 P
: Số logical CPU (P = processors)
🧠 7. Khi nào nên lo về GC?
Latency spikes
Có thể là stop-the-world phase
CPU usage tăng
GC hoạt động quá thường xuyên
Memory tăng không giảm
Object bị giữ reference (memory leak)
✅ Tổng kết
SetGCPercent
Điều chỉnh khi nào GC chạy
sync.Pool
Giảm cấp phát heap
MemStats
Theo dõi GC trong runtime
GODEBUG=gctrace=1
Debug GC
Escape Analysis
Tối ưu để giữ object trong stack
Last updated