Improving Python: How we made pip install twice as fast

Bài tóm tắt Man Group 2025 3. Quy mô lớn Độ khó: Trung bình

Man Group · 2025 · 3. Quy mô lớn · Độ khó: Trung bình — bài gốc

Bối cảnh

  • Man Group là quỹ đầu tư giao dịch hệ thống hơn 35 năm; hơn một phần ba nhân sự là technologist, quant và data scientist. Python là nền tảng phát triển chính; đội Python Platform phục vụ hàng trăm người dùng mỗi ngày.
  • Khi các package manager mới tuyên bố nhanh hơn pip 10–100 lần, đội nhận ticket điều tra. Một kỹ sư có hai mươi năm kinh nghiệm Python profile pip với bộ gói đại diện: Torch/TensorFlow (2–5 GB giải nén, cốt lõi cho nghiên cứu ML), NumPy/Pandas, Plotly (khoảng 15.000 file), Jupyter (khoảng 80 phụ thuộc bắc cầu).

Thay đổi chính

  • Profile cho thấy thời gian bị chia nhỏ giữa tải, phân giải phụ thuộc và giải nén, nên tăng tốc một phần không làm cả pip nhanh gấp nhiều lần. Tải nằm bên trong phân giải phụ thuộc vì pip chỉ biết phụ thuộc sau khi tải gói.
  • Các bản vá gửi lên pip:
    • Tạo lại thư mục cha cho từng file khi giải nén (14.425 lời gọi với Plotly → 1.538): nhanh hơn khoảng 5%.
    • Lỗi bậc hai khi in tóm tắt cuối (mỗi lần tra phiên bản lặp qua mọi gói đã cài): gần 300 gói thì khoảng 30% thời gian là để in tóm tắt; "khoảng lặng" mà mọi người tưởng là đang giải nén thật ra là đang chuẩn bị bản tóm tắt.
    • Giải nén: bỏ qua file 0 byte (5–10% file là __init__ rỗng), đặt kích thước block bằng kích thước file với file nhỏ: nhanh hơn khoảng 10%. Viết lại zipfile của thư viện chuẩn có thể nhanh hơn 20–30% nhưng nằm ngoài pip.
    • Tải: requests mặc định đọc theo chunk 10 KB; thanh tiến trình refresh 30 lần/giây chiếm tới 30% thời gian. Sau tune: 60 → 460 MB/s; với máy mới cho Artifactory nội bộ, trung bình trên 600 MB/s.
    • Đọc biến môi trường proxy chiếm khoảng 5% (đọc lặp lại cho mỗi request, cả chữ hoa lẫn thường); đã có người khác sửa trong CPython 3.12, nhanh hơn khoảng 5 lần.
    • fsync hai lần mỗi gói chiếm khoảng 7%; PR bỏ fsync không được merge vì tranh luận về hành vi giữa các OS.
    • Cache lru_cache phân tích chuỗi requirement quá nhỏ (2.048): tăng lên 8.192 thì nửa thời gian.

Vì sao

  • Kết quả: pip install nhanh gấp đôi, pip download nhanh gấp 7 lần, CPU giảm 3 lần. Môi trường mới cho developer và researcher dựng nhanh hơn, chi phí CI/CD giảm rõ.
  • Tìm lỗi và viết patch mất khoảng 2 tuần; đưa PR lên và được merge mất thêm 2 tháng.

Bài học cho SWE

  • Profile công cụ "ai cũng dùng"; lỗi bậc hai và cấu hình mặc định tệ có thể nằm đó hàng năm.
  • Thanh tiến trình, log, kiểm biến môi trường: phần phụ có thể tốn ngang việc chính.
  • Sửa upstream thay vì fork khi có thể; nâng phiên bản runtime cũng mang lại tối ưu miễn phí.

Liên quan