3 điểm bởi GN⁺ 2025-10-10 | 1 bình luận | Chia sẻ qua WhatsApp
  • Python 3.14 vừa được phát hành lần này cho thấy hiệu năng nhanh nhất trong số các phiên bản CPython từ trước đến nay
  • Ở đơn luồng, 3.14 cải thiện khoảng 27% so với 3.13, trong khi mức tăng hiệu năng của JIT là không đáng kể, và trình thông dịch Free-threading hơi chậm hơn ở đơn luồng
  • Ở đa luồng, trình thông dịch FT nhờ hiệu ứng loại bỏ GIL đã cho mức tăng tốc 3,1 lần với Fibonacci2 lần với sắp xếp nổi bọt, nên hiệu quả với tác vụ đa luồng thiên về CPU
  • Kết luận là 3.14 là bản CPython nhanh nhất, khuyến nghị dùng từ 3.11 trở lên, Pypy vẫn rất nhanh, còn JIT thì cần cải thiện thêm về độ trưởng thành

Giả định và giới hạn của benchmark

  • Ngay sau khi Python 3.14 chính thức phát hành, tác giả đã chia sẻ kết quả benchmark hiệu năng giữa nhiều phiên bản Python và một số ngôn ngữ khác
  • Bài test này được thực hiện bằng các hàm đệ quy đơn giản (Fibonacci) và lặp (sắp xếp nổi bọt) viết hoàn toàn bằng mã Python thuần
  • Trong môi trường phát triển thực tế, Python thường được dùng xen kẽ với mã native như C/C++/Rust, nên kết quả này không tương ứng 1:1 với tình huống thực tế

Ma trận thử nghiệm

  • Môi trường thử nghiệm
    • Bao gồm 6 phiên bản Python (3.9~3.14), Pypy, Node.js và Rust
    • Trình thông dịch Python: Standard, JIT, Free-threading (mỗi loại áp dụng từ 3.13 trở lên)
    • Script kiểm thử: Fibonacci (fibo.py), bubble sort (bubble.py)
    • Chế độ luồng: đơn luồng, 4 luồng
    • Máy thử nghiệm: Linux (Framework i5), macOS (M2)
  • Phiên bản Node.js và Rust cũng được đưa vào để tham khảo so sánh

Script kiểm thử

  • Fibonacci (fibo.py): dùng cấu trúc đệ quy, chạy fibo(40) trên từng môi trường
  • Bubble sort (bubble.py): sắp xếp 10.000 số ngẫu nhiên
  • Mỗi bài test được lặp lại 3 lần để lấy giá trị trung bình
  • Mã kiểm thử được công khai tại kho lưu trữ GitHub

Benchmark #1: Fibonacci (đơn luồng)

  • Python 3.14 ghi nhận tốc độ nhanh hơn khoảng 27% so với 3.13 (6,59 giây so với 8,26 giây)
  • Từ phiên bản 3.11, Python đã chuyển từ mức “rất chậm” sang “đỡ chậm hơn một chút”
  • Pypy nhanh hơn khoảng 5 lần so với 3.14, tương đương Node.js, còn Rust thì vượt trội và nhanh nhất áp đảo
  • Free-threading vẫn chậm hơn bản Standard ở đơn luồng, nhưng khi sang 3.14 thì khoảng cách tốc độ đã giảm xuống (đạt khoảng 91%)

JIT, trình thông dịch Free-threading

  • JIT không mang lại cải thiện hiệu năng đáng cảm nhận với cấu trúc hàm đệ quy này
  • Free-threading ngược lại cho kết quả hơi chậm hơn ở đơn luồng
  • Giới hạn cải thiện hiệu năng của JIT có thể khác nhau tùy cấu trúc hàm

Benchmark #2: Bubble sort (đơn luồng)

  • Python 3.14 nhanh hơn đôi chút so với 3.11, nhưng chênh lệch nhỏ hơn Fibonacci (3.14: 2,18 giây, 3.11: 2,48 giây)
  • Pypy nhanh hơn khoảng 18 lần so với 3.14
  • JIT có nhanh hơn nhẹ trên Linux, nhưng trên macOS gần như không có khác biệt

Benchmark #3: Fibonacci (đa luồng)

  • Với trình thông dịch Standard, do GIL (Global Interpreter Lock), việc tăng số luồng không mang lại tốc độ như kỳ vọng
  • Trình thông dịch Free-threading (3.14) nhanh hơn 3,1 lần so với Standard
  • Hầu như không quan sát thấy ảnh hưởng của JIT
  • Chỉ có kết quả của Pypy được đo trong phần này; Node.js/Rust không được so sánh ở bài test này

Benchmark #4: Bubble sort (đa luồng)

  • Free-threading (3.14 FT) cho kết quả nhanh hơn 2 lần so với Standard (3.14), đặc biệt nổi bật ở các tác vụ thiên về CPU
  • JIT không cho thấy ưu thế hiệu năng rõ rệt
  • Hiệu năng Free-threading trên Mac khá nổi bật

Kết luận

  • CPython 3.14 cho thấy hiệu năng nhanh nhất trong số các bản CPython hiện có
  • Nếu khó nâng cấp, nên dùng phiên bản từ 3.11 trở lên
  • Trình thông dịch JIT trên thực tế chỉ mang lại mức tăng tốc khó cảm nhận
  • Trình thông dịch Free-threading có ưu thế rõ rệt trong các tình huống đa luồng thiên về CPU
  • Pypy nhanh vượt trội và rất đáng để tiếp tục khám phá

Khác

  • Kết quả có thể thay đổi tùy nhiều biến số môi trường, nên khuyến nghị tự benchmark và xác nhận trực tiếp
  • Có thể tham khảo thêm chi tiết và mã nguồn trong kho lưu trữ GitHub

1 bình luận

 
GN⁺ 2025-10-10
Ý kiến trên Hacker News
  • Tôi muốn kể về một người đã thay đổi cuộc đời mình. Tôi đã làm website đầu tiên nhờ Flask mega tutorial, và ngay trước lúc ra mắt thì bị mắc ở một phần quan trọng liên quan đến xử lý file hỏng trong Flask. Tôi đặt câu hỏi, được giải quyết bằng một câu trả lời trên Stack Overflow, rồi lập tức áp dụng vào site. Sau đó site lan truyền rất mạnh. Để tham khảo, tôi để lại link câu trả lời stackoverflow link

    • Không liên quan đến Flask lắm, nhưng tôi thực sự không thích logo Flask mới. Logo cũ có cảm giác vintage và như được làm thủ công, còn logo mới trông như tác phẩm WordArt nghịch cho vui của học sinh cấp ba. Logo cũ, logo mới

    • Tôi muốn hỏi liệu site bạn làm có phải là yout.com không. Cũng tò mò không biết bạn còn dùng Flask không

    • Sẽ thật tuyệt nếu một ngày nào đó bạn lại vibe coding và hồi sinh site microphonetest.com

  • Tôi khuyên không nên viết benchmark theo kiểu đo thời gian bên trong vòng lặp rồi cộng dồn lại. Tốt hơn là đo thời gian chạy của cả vòng lặp rồi chia cho số lần lặp. Kết quả có thể bị méo do jitter sinh ra từ chính việc đo thời gian

    • Khuyên dùng timeit trong thư viện chuẩn timeit docs
  • Tôi lo Python sẽ bị “đóng băng” ở phiên bản 3.14 như TeX liên kết Reddit

    • Khi thấy ý kiến hy vọng nó đừng “dừng lại”, tôi lại thấy mới mẻ ở chỗ Donald Knuth coi trọng một hệ thống liên tục cho ra cùng một kết quả hơn là thay đổi. Trong một thế giới mà mọi thứ chỉ sau vài năm đã bị xem là lỗi thời, tôi thấy sự ám ảnh rằng cứ có thứ OOO mới ra là phải đổi ngay gần như là một căn bệnh. Không có lý do gì mà chúng ta không thể viết code để dùng suốt 100 năm. Suy cho cùng, code là toán học. Cũng như chẳng ai bị coi là lạc hậu chỉ vì dùng đa thức được phát minh từ hàng nghìn năm trước, tôi nghĩ cũng cần có thái độ gắn bó với những thứ đã được kiểm chứng. Không nhất thiết lúc nào cũng phải bám vào bản mới hay công cụ mới. Những người viết code không cần thay đổi mới là những người thật sự đóng góp

    • Một bình luận nói rằng tình huống này hợp một cách đáng ngạc nhiên với trò đùa về πthon

  • Mỗi lần có tin tức về Python, tôi lại thấy tiếc vì đến năm 2025 PyPy vẫn đi theo một nhánh riêng. Tôi tự hỏi liệu Python không có GIL someday có thể dẫn tới cả C FFI không có GIL hay không. Tôi nghĩ điều đó sẽ thực sự giúp ích lớn cho Python

    • C FFI từ lâu đã có thể tự giải phóng GIL bằng tay, nên tôi hơi tò mò chính xác ý này nghĩa là gì

    • Tôi nghĩ việc bắt đầu từ C rồi sinh ra nhiều phương ngữ khác nhau qua nhiều triển khai compiler là một hệ sinh thái lành mạnh, vì nó thúc đẩy thử nghiệm và phát triển. Tôi cũng không cho rằng PyPy và CPython khác nhau quá lớn, và mức tương thích cũng cao hướng dẫn tương thích của pypy

    • freethreading chính là để phục vụ mục tiêu đó. Theo tôi biết thì vẫn còn nhiều thư viện C FFI chưa được thay đổi để chạy không cần GIL, nên chưa thể dùng freethreading làm mặc định

    • Python đã thêm JIT thử nghiệm, tức là đã tiến thêm một bước về phía PyPy. Tôi không biết tương lai họ sẽ tự làm JIT mới hay hợp nhất với PyPy, nhưng tôi tin họ đã học được rất nhiều từ PyPy

    • Tôi muốn hỏi liệu bạn có nghĩ chuyện này (việc hợp nhất các hệ triển khai riêng biệt) có thể thay đổi không. Một kịch bản trong đó Python tình cờ đưa vào thêm một breaking change khác làm hại hiệu năng sẽ gây thiệt hại cho rất nhiều người dùng. Tôi nghi ngờ liệu tổ chức Python có thật sự muốn điều đó không

  • Thật thú vị khi PyPy vẫn nhanh hơn cả CPython free threaded ngay cả với code đa luồng

  • Điều nổi bật là quá trình chuyển sang non-GIL diễn ra rất mượt. So với lần chuyển từ 2 sang 3, lần này thực sự ấn tượng. Việc nhanh chóng đạt tới tốc độ chuẩn cũng rất đáng kỳ vọng, và tôi hy vọng các điểm không tương thích rồi cũng sẽ sớm biến mất

  • Nếu muốn nhanh chóng tự benchmark thử, tôi khuyên dùng repo fast_langton_ant. Chạy kiểu như python3 server.py -s 10000000 -n là được

  • Tôi thắc mắc không biết tính năng bình luận thu gọn (fold comment) có áp dụng theo karma hay tùy chọn nào khác không. Câu chuyện Miguel giúp đỡ là bài được thích nhất nên rất ấn tượng, nhưng khi chỉ muốn xem các ý liên quan trực tiếp đến bài viết thì đây là lần đầu tôi nhận ra không có chức năng thu gọn

  • Tôi nghĩ thật khó dùng benchmark chỉ gồm vòng lặp đơn giản và phép toán số nguyên để đánh giá mức độ thực tế của việc dùng Python. Hash map hay xử lý chuỗi sẽ gần với code thực tế hơn. Nhiều người dùng Python giao phần tính toán số cho thư viện ngoài

    • Benchmark vốn dĩ luôn được thiết kế để đo theo một tiêu chí cụ thể. Tác giả đã giải thích mục tiêu trong bài, nên nếu tò mò thì nên đọc thêm

    • Tôi cũng ước đây là một bài phân tích kỹ hơn, nhưng dù vậy những benchmark kiểu này lại hợp với cách tôi dùng thực tế hơn. Trường hợp của tôi là chủ yếu tạo các mô phỏng Monte Carlo hoặc tính toán khoa học đơn giản lặp đi lặp lại cho nhiều bài toán khác nhau. Với các mô phỏng dùng một lần, tôi không nhất thiết phải dùng thuật toán nhanh hay thư viện mình không quen. Đôi khi mất 10 phút cũng không sao (dĩ nhiên tôi vẫn chủ yếu dùng scipy, numpy). Vì tôi thường xuyên thay đổi giả định lặp đi lặp lại, tôi cố giữ mọi thứ đơn giản nhất có thể. Tính dễ đọc và khả năng viết code tại chỗ quan trọng hơn, và việc không tối ưu tốt cũng không sao cả (ví dụ như Fibonacci, bubble sort, vòng for lồng nhau). Nếu thực sự cần hiệu năng thì tôi sẽ tự triển khai phần đó bằng cpp/zmp/pybind/numba

    • Sẽ thực tế hơn với cách dùng Python phổ biến nếu benchmark có thêm các ví dụ như gọi endpoint FastAPI hay tính toán bằng numpy. Dù các phần đó có thể không phải pure Python, nhưng trên thực tế rất nhiều người dùng Python theo cách đó

  • Tôi nghi ngờ việc benchmark chỉ bằng tight loop và phép toán int thì thực tế đến mức nào

  • Tôi tò mò không biết experimental tail call interpreter mới (tùy chọn --with-tail-call-interp) có được đưa vào benchmark không tài liệu chính thức về tail-call-interp. Vì không thấy nhắc trong kết quả thử nghiệm nên tôi đoán là chưa được đưa vào. Tôi muốn so sánh xem tail call interpreter chênh lệch bao nhiêu so với các triển khai hiện có khác

    • Bản build Python tôi dùng có bật tail call (tùy chọn --with-tail-call-interp). Tôi không chắc tối ưu hóa đó có áp dụng cho tail call đệ quy hay không, nhưng nếu có thì lẽ ra phải thấy cải thiện hiệu năng trong bài test Fibonacci