白話文解說 Python Immortal Objects
Python 3.12 新增一個稱為 Immortal Objects 的功能,正如其名是個永生的物件(印和闐!印和闐!印和闐!
這個功能與平行處理的效能跟記憶體用量有關,值得說明一下它所帶來的好處!
故事是這樣的, Instagram 的開發團隊主要是使用 Django 提供服務,而且他們也使用了 pre-fork 架構預先 fork 出多個 processes 以提高處理 requests 的效能。
這些 fork 出來的 processes 之間透過共享記憶體(shared memory)共享一些 Immutable 的資料(我猜可能是 GeoIP 資料庫或是黑名單等等之類,以 Instagram 的量級來說應該有很多資料需要共享)。
而 fork 的時候, parent process 的資料會共享給 child process 使用(這就是一種共享記憶體),這樣一來建立 child process 就會非常快,畢竟可以減少複製資料的成本,只有在 child process 想對共享資料進行寫入操作的時候,這份共享的資料才會複製到 child process 的記憶體內,這機制就稱為 Copy on Write, 是作業系統的運作機制。
但是 Instagram 發現他們記憶體的用量會隨著服務的 requests 逐步上升,與他們原本以為共享記憶體可以節省記憶體用量的預期有所出入,於是 Instagram 開發團隊深入研究後發現,原來資料的部分是 Immutable 沒錯,可是問題出在 Python 的 GC 機制,會對 Python object 的 reference count 以及 GC header 進行修改,這就造成 child process 對共享記憶體有寫入的行為發生,進而導致 Copy on Write 的發生,這些共享資料就被複製進 child process 的記憶體內,造成記憶體用量上升。
他們解決這個問題的方法,就是設計 Immortal Objects 讓 Python 的 GC 機制不會去改這個 object 的 reference count 以及 GC header, 確保不會產生 Copy on Write, 而結果也成功證實這個做法可以有效降低記憶體用量,進而提升 Python 的效能。
最後他們也很善意的提出 PEP-683 回饋給 Python 社群,最後在 3.12 成功導入 Immortal Objects!
期待 Python 3.12 早日推出正式版!