Module 4 — Quản lý bộ nhớ ngôn ngữ bậc cao: tổng quan
Ai giải phóng bộ nhớ bạn cấp phát — bạn hay runtime. Module so sánh cấp phát thủ công với GC, ref-counting vs tracing, và vì sao vẫn rò bộ nhớ dù có GC.
TL;DR: Trong C, mọi byte bạn malloc đều phải được free đúng chỗ đúng lúc — trách nhiệm thuộc về bạn. Trong Java, Go, Python, một garbage collector chạy trong runtime tự tìm và thu hồi bộ nhớ không còn ai dùng. Hai triết lý này đánh đổi khác nhau: thủ công cho kiểm soát và chi phí thấp, GC cho an toàn và code đơn giản hơn. Nhưng GC không phải viên đạn bạc — bộ nhớ vẫn rò nếu bạn giữ tham chiếu mà quên buông, và GC pause có thể gây vấn đề nghiêm trọng ở hệ thống latency-nhạy. Module này đi từ nguyên lý đến thực tế: hiểu cơ chế để không bị bất ngờ.
Vì sao module này tồn tại
Khi bạn gọi new trong Java hay Python, ai giải phóng bộ nhớ đó khi bạn không còn cần nữa? Câu trả lời khác hoàn toàn tuỳ ngôn ngữ — và sự khác nhau đó ảnh hưởng trực tiếp tới thiết kế, hiệu năng, và loại bug bạn sẽ gặp.
Trong C, quên gọi free là bug — chương trình ăn RAM cho đến khi bị kill. Gọi free hai lần là undefined behavior, có thể sập cả process. Trong Java, bạn không gọi free bao giờ — nhưng có những trường hợp bộ nhớ vẫn không được giải phóng dù object "có vẻ" không dùng nữa. Hiểu vì sao đòi hỏi biết GC hoạt động theo cơ chế gì.
Module này trả lời: ai dọn rác, dọn bằng cách nào, và khi nào dọn không được.
Sau module này bạn sẽ
- Compare cấp phát thủ công (
malloc/free) với garbage collection tự động về an toàn và chi phí. - Explain ref-counting và tracing GC hoạt động thế nào, ưu nhược điểm mỗi cách.
- Diagnose memory leak trong ngôn ngữ có GC và giải thích vì sao GC không cứu được.
- Refactor một chương trình chậm vì cache miss (AoS sang SoA) và đo cải thiện trước-sau.
Lộ trình module
Bài 01 đặt bức tranh hai triết lý: cấp phát thủ công (C) đặt trách nhiệm lên lập trình viên với các bug điển hình, đối chiếu với GC tự thu hồi qua khái niệm reachability. Bài 02 đi vào hai cơ chế GC phổ biến nhất: ref-counting (CPython, Swift) đếm tham chiếu và giải phóng tức thì, đối chiếu với tracing GC (Java, Go) trace từ root theo chu kỳ. Bài 03 trả lời câu hỏi thực tế: vì sao code Java vẫn có memory leak dù đã có GC — khai thác khái niệm logical leak qua strong reference. Bài 04 là capstone kết hợp kiến thức: tối ưu cache miss (AoS→SoA) với đo trước-sau. Bài 05 tổng kết và cheat sheet.
flowchart LR A["01 Manual vs GC"] --> B["02 Ref-counting vs tracing"] B --> C["03 Leak co GC"] C --> D["04 Capstone cache miss"]
Yêu cầu trước khi bắt đầu
- Module 1 (stack/heap, con trỏ, bố cục bộ nhớ tiến trình) — đã học heap và
malloclấy bộ nhớ từ đâu. - Module 2 (cache, locality, AoS vs SoA) — bài 04 (capstone) xây trực tiếp trên AoS vs SoA.
- Module 3 (bộ nhớ ảo, page fault) — hữu ích khi hiểu GC tracing chạm trang lạnh có thể gây page fault.
Time budget
- Module: ~1.5 giờ đọc.
| Bài | Chủ đề | Phút |
|---|---|---|
| 01 | Cấp phát thủ công vs garbage collection | 18 |
| 02 | Ref-counting vs tracing GC | 18 |
| 03 | Vì sao vẫn rò bộ nhớ dù có GC | 16 |
| 04 | Capstone — tối ưu cache miss, đo trước-sau | 25 |
| 05 | Tổng kết & cheat sheet | 12 |
Cách học module này hiệu quả
- Đừng bỏ qua bài 01 dù bạn không viết C. Hiểu manual memory giúp bạn trân trọng GC đúng mức — và biết GC bảo vệ khỏi gì, không bảo vệ khỏi gì.
- Chạy thử GC pause. Java có flag
-verbose:gchoặc dùng GC log để thấy thực tế GC xảy ra khi nào. Bài 02 cung cấp context đọc log đó. - Bài 03 là bài quan trọng nhất module với lập trình viên Java/Go/Python. Mọi "leak trong ngôn ngữ có GC" đều về một nguyên nhân gốc rễ giải thích trong bài đó.
Bài tiếp theo: Cấp phát thủ công vs garbage collection
Bài này có giúp bạn hiểu bản chất không?
Hỏi đáp về bài này
Chưa có câu hỏi
Có gì chưa rõ trong bài? Đặt câu hỏi đầu tiên — câu trả lời từ cộng đồng giúp bạn (và người sau).
Đặt câu hỏi đầu tiên