對於我們這一代工程師而言,垃圾回收(Garbage Collection, GC) 是一項巨大的恩惠。
它讓我們從繁瑣的記憶體管理中解脫,可以更專注於業務邏輯和創造性的工作。
從 PHP、Python 到 JavaScript 和 Golang,GC 在各種現代程式語言中扮演著無聲的守護者。
然而,這種便利性並非沒有代價。當我們追求極致性能和穩定性時,這些「自動」的機制可能會成為隱藏的阻礙。
當系統規模擴大或對效能要求極高時,GC 的局限性便會顯現。
在開發高併發、低延遲的服務(如廣告競價系統)時,即使 Golang 的 GC 已經將 Stop-the-World (STW) 時間壓縮至亞毫秒級,但在每秒數十萬次請求的場景下,這短暫的停頓仍然會導致少數請求的延遲飆升,錯過關鍵的時間窗口。GC 的運作時機和時長是不可預測的,這對需要穩定、可預測性能的系統來說是一個嚴重的問題。
全域直譯器鎖(Global Interpreter Lock, GIL) 讓 Python 在 CPU 密集型的多執行緒任務上表現不佳。為了利用多核心,開發者通常會轉向多進程,但這又帶來了新的問題:
雖然 GC 在每個進程中正常運作,但它無法從根本上解決由 GIL 帶來的架構性挑戰。
在事件驅動、非同步回呼的 JavaScript 世界中,記憶體洩漏是一個隱蔽的敵人。一個未移除的事件監聽器、一個被意外持有的閉包引用,都可能導致一塊記憶體永遠無法被 GC 回收。這會造成應用程式的記憶體佔用緩慢且穩定地增加,最終導致服務崩潰。GC 就像一位盡職的清潔工,但他無法清理那些被我們錯誤地標示為「還在用」的垃圾。
這些經歷讓我們意識到,GC 並非萬靈丹,它是一種權衡:我們用控制權換取了便利性。在記憶體管理上,軟體開發似乎有三條不同的道路:
Rust 透過一套嚴格的 「所有權(Ownership)」、「借用(Borrowing)」 和 「生命週期(Lifetimes)」 規則,將記憶體管理的重擔從不確定的執行期轉移到嚴謹的編譯器。
意思是記憶體安全檢查在程式執行前就已完成,程式碼在執行時無需額外的 GC 開銷。
編譯器成為了最嚴格、最可靠的「記憶體管家」,能及早發現那些可能導致記憶體洩漏或安全問題的程式碼。
對習慣了 GC 便利性的工程師來說,Rust 的所有權模型是一種顛覆性的思考方式。它承諾了一個新的未來:我們可以編寫出如 C/C++ 般高效的底層程式碼,同時又能享有如 Go/Python 般的高度安全性。
這就是 Rust 帶來的革命,它從根本上改變了我們對記憶體管理的理解,並引導我們成為更嚴謹的開發者。
記憶體管理 - JavaScript | MDN:介紹了記憶體生命週期以及垃圾回收演算法(引用計數、標記-清除)的基本原理,是理解 GC 的絕佳起點。
A Guide to the Go Garbage Collector - The Go Programming Language:針對 Go 的文章,前段對「Stop-the-World (STW)」以及 GC 為何需要權衡有正確的解釋。
Getting to Go: The Journey of Go's Garbage Collector - The Go Programming Language:來自 Go 官方部落格的文章,詳細闡述了 Go 團隊如何一步步將其 GC 的延遲從數百毫秒優化到亞毫秒級別的奮鬥歷程。
What Is the Python Global Interpreter Lock (GIL)? – Real Python:Real Python 的經典文章,詳細解釋了 Python 的 GIL 是什麼、為何存在,以及它對多執行緒程式的真實影響。