Dismissing Python Garbage Collection at Instagram
Bài tóm tắt Instagram 2017 3. Quy mô lớn Độ khó: Nâng cao
Instagram · 2017 · 3. Quy mô lớn · Độ khó: Nâng cao — bài gốc
Bối cảnh
- Web server Django chạy uWSGI ở chế độ pre-fork: process master fork ra hàng chục worker để chia sẻ bộ nhớ theo copy-on-write (CoW). Worker bị restart khi RSS vượt ngưỡng để tránh OOM.
- Quan sát: ngay sau khi fork, shared memory của mỗi worker tụt từ ~250MB xuống ~140MB trong vài giây. Khoảng 1/3 bộ nhớ chuyển từ shared sang private.
Thay đổi chính (4 lần thử)
- Giả thuyết refcount trên code object ("copy-on-read": đọc object cũng tăng refcount, tức là ghi vào page). Họ vá CPython để tắt refcount cho code object. Không có tác dụng, và cũng không có metric nào chứng minh giả thuyết. Bài học họ tự rút ra: chứng minh giả thuyết trước khi làm.
- Đo page fault bằng
perf: thủ phạm làcollecttronggcmodule.c. GC xáo trộn danh sách liên kết các thế hệ object, mà header GC nằm ngay trong object, nên page bị CoW.gc.disable()không ăn thua vì thư viện msgpack tựgc.enable()lại. Dùnggc.set_threshold(0)thì được: shared memory 140→225MB, tiết kiệm 8GB RAM mỗi máy (~25% RAM của fleet Django), throughput tầng Django tăng >10%. - Lên cả cluster thì restart chậm (từ <10 giây lên >60 giây). Nguyên nhân: Python chạy một lần GC cuối trong
Py_Finalizelúc tắt, làm bộ nhớ vọt lên. Họ thêm cờ runtime vào CPython để tắt GC hoàn toàn, nhưng máy CPU đời cũ (Sandybridge) vẫn lỗi vì các bước dọn dẹp khác lúc tắt. - Giải pháp cuối, 2 dòng:
gc.set_threshold(0)+atexit.register(os._exit, 0), tức là tự thoát ngay sau các atexit hook của app, bỏ qua dọn dẹp của CPython. Kết quả: ~10% capacity toàn cầu.
Vì sao
- Không có GC, bộ nhớ vẫn không phình, vì cơ chế giải phóng chính của CPython là reference counting; GC chỉ để phá vòng tham chiếu.
- Lợi ích đến từ hai phía: (a) thêm RAM để chạy thêm worker; (b) IPC của CPU tăng ~10% vì cache-miss giảm 2–3% (nhiều worker trỏ chung một vùng nhớ vật lý).
Bài học cho SWE
- Đo trước, đoán sau. Lần thử đầu sai vì không có metric;
perfchỉ đúng thủ phạm. - Thư viện bên thứ ba có thể âm thầm hoàn tác cấu hình runtime của bạn.
- Luôn thử trên phần cứng/client cũ nhất, vì đó là nơi dễ vỡ nhất.
- Hiểu runtime sâu có thể cho ~10% capacity mà không phải viết lại. Ngược hướng với Discord bỏ Go vì GC (Discord 2020).
Liên quan
Được nhắc tới trong
Công ty (1)
Bài tóm tắt (4)