- Python 3.14 ที่เปิดตัวครั้งนี้แสดงประสิทธิภาพที่เร็วที่สุดในบรรดาเวอร์ชัน CPython ทั้งหมดจนถึงตอนนี้
- ในงานแบบเธรดเดียว 3.14 ทำได้ดีขึ้นจาก 3.13 ประมาณ 27% ขณะที่ ประสิทธิภาพของ JIT ดีขึ้นเพียงเล็กน้อย และ อินเทอร์พรีเตอร์ Free-threading ช้ากว่าเล็กน้อยในโหมดเธรดเดียว
- ในงานหลายเธรด อินเทอร์พรีเตอร์ FT แสดงผลจากการตัด GIL ออก โดยเร่งความเร็วได้ระดับ Fibonacci 3.1 เท่า และ Bubble Sort 2 เท่า จึงมีประโยชน์กับ งานมัลติเธรดที่ใช้ CPU หนัก
- สรุปคือ 3.14 เร็วที่สุดในบรรดา CPython, แนะนำให้ใช้ 3.11 ขึ้นไปหากเป็นไปได้, Pypy ยังเร็วมาก และ JIT ยัง ต้องการความสุกงอมเพิ่มขึ้น
สมมติฐานและข้อจำกัดของการเบนช์มาร์ก
- หลังการเปิดตัวอย่างเป็นทางการของ Python 3.14 ได้มีการแชร์ผล การเบนช์มาร์กประสิทธิภาพ ระหว่าง Python หลายเวอร์ชันและภาษาอื่น ๆ
- การทดสอบนี้ใช้ฟังก์ชันแบบเรียบง่ายที่เขียนด้วย โค้ด Python ล้วน ได้แก่แบบเรียกซ้ำ (Fibonacci) และแบบวนซ้ำ (Bubble Sort)
- ในงานพัฒนาจริงมักมีการใช้งานร่วมกับ native code เช่น C/C++/Rust ดังนั้นผลลัพธ์นี้จึง ไม่สามารถเทียบกับสถานการณ์จริงแบบ 1:1
เมทริกซ์การทดสอบ
- สภาพแวดล้อมการทดสอบ
- Python 6 เวอร์ชัน (3.9~3.14), รวม Pypy, Node.js, Rust
- Python อินเทอร์พรีเตอร์: มาตรฐาน (Standard), JIT, Free-threading (แต่ละแบบมีใน 3.13 ขึ้นไป)
- สคริปต์ทดสอบ: Fibonacci (fibo.py), Bubble Sort (bubble.py)
- โหมดเธรด: เธรดเดียว, 4 เธรด
- เครื่องทดสอบ: Linux (Framework i5), macOS (M2)
- มีการเปรียบเทียบเวอร์ชันของ Node.js และ Rust ไว้เป็นข้อมูลอ้างอิงด้วย
สคริปต์ทดสอบ
- Fibonacci (fibo.py): ใช้โครงสร้างแบบเรียกซ้ำ รัน
fibo(40) ในแต่ละสภาพแวดล้อม
- Bubble Sort (bubble.py): เรียงลำดับตัวเลขสุ่ม 10,000 ตัว
- การทดสอบแต่ละรายการทำซ้ำ 3 ครั้งเพื่อหาค่าเฉลี่ย
- โค้ดทดสอบเผยแพร่ไว้ใน GitHub repository
Benchmark #1: Fibonacci (เธรดเดียว)
- Python 3.14 ทำความเร็วได้ดีขึ้นจาก 3.13 ประมาณ 27% (6.59 วินาที vs 8.26 วินาที)
- ตั้งแต่เวอร์ชัน 3.11 เป็นต้นมาได้เปลี่ยนจากระดับ "ช้ามาก" เป็น "ช้าน้อยลงบ้าง"
- Pypy เร็วกว่า 3.14 ราว 5 เท่า, อยู่ระดับเดียวกับ Node.js และ Rust เร็วที่สุดแบบทิ้งห่าง
- Free-threading ยังช้ากว่าเวอร์ชันมาตรฐานในโหมดเธรดเดียว แต่เมื่อเป็น 3.14 ช่องว่างของความเร็วลดลงแล้ว (อยู่ที่ราว 91%)
อินเทอร์พรีเตอร์ JIT และ Free-threading
- JIT ไม่ให้การเพิ่มประสิทธิภาพที่รู้สึกได้ กับโครงสร้างฟังก์ชันแบบเรียกซ้ำนี้
- Free-threading กลับให้ผล ช้าลงเล็กน้อย ในโหมดเธรดเดียว
- ข้อจำกัดด้านประสิทธิภาพของ JIT อาจแตกต่างกันไปตามโครงสร้างของฟังก์ชัน
Benchmark #2: Bubble Sort (เธรดเดียว)
- Python 3.14 เร็วกว่า 3.11 เล็กน้อย แต่ช่องว่างน้อยกว่ากรณี Fibonacci (3.14: 2.18 วินาที, 3.11: 2.48 วินาที)
- Pypy เร็วกว่า 3.14 ราว 18 เท่า
- JIT เร็วขึ้นเล็กน้อยใน Linux แต่บน macOS แทบไม่เห็นความแตกต่าง
Benchmark #3: Fibonacci (หลายเธรด)
- ในอินเทอร์พรีเตอร์มาตรฐาน การเพิ่มจำนวนเธรดไม่ได้เร็วขึ้นเท่าที่คาดเพราะมี GIL (Global Interpreter Lock)
- อินเทอร์พรีเตอร์ Free-threading (3.14) เร็วกว่าเวอร์ชันมาตรฐาน 3.1 เท่า
- แทบไม่เห็นผลของ JIT
- มีการวัดเฉพาะผลของ Pypy เท่านั้น โดยไม่ได้เปรียบเทียบ Node.js/Rust ในการทดสอบนี้
Benchmark #4: Bubble Sort (หลายเธรด)
- Free-threading (3.14 FT) เร็วกว่าเวอร์ชันมาตรฐาน (3.14) 2 เท่า (จุดเด่นชัดเจนโดยเฉพาะกับงานที่ใช้ CPU หนัก)
- JIT ไม่มีความได้เปรียบด้านประสิทธิภาพที่ชัดเจน
- ประสิทธิภาพของ Free-threading บน Mac โดดเด่นเป็นพิเศษ
บทสรุป
- CPython 3.14 แสดงประสิทธิภาพที่เร็วที่สุดในบรรดา CPython ที่มีอยู่ในตอนนี้
- หากอัปเกรดยาก แนะนำให้ใช้เวอร์ชัน 3.11 ขึ้นไป
- อินเทอร์พรีเตอร์ JIT ให้ความเร็วที่ผู้ใช้รู้สึกได้เพิ่มขึ้นเพียงเล็กน้อย
- อินเทอร์พรีเตอร์ Free-threading มีข้อได้เปรียบชัดเจนในสถานการณ์มัลติเธรดที่ใช้ CPU หนัก
- Pypy เร็วอย่างทิ้งห่างและยังมีคุณค่าที่ควรสำรวจต่อ
อื่น ๆ
- ผลลัพธ์อาจแตกต่างกันไปตามตัวแปรของสภาพแวดล้อม จึงแนะนำให้เบนช์มาร์กและตรวจสอบด้วยตนเอง
- ดูรายละเอียดเพิ่มเติมและโค้ดได้จาก GitHub repository
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
อยากเล่าเกี่ยวกับคนคนหนึ่งที่เปลี่ยนชีวิตผม ตอนสร้างเว็บไซต์แรกผ่าน Flask mega tutorial ผมติดอยู่ตรงส่วนสำคัญของ Flask ที่จัดการไฟล์เสียก่อนเปิดตัวไม่นาน พอถามไปก็ได้คำตอบใน Stack Overflow ที่ช่วยแก้ปัญหาได้ และผมก็เอาไปใช้กับไซต์ได้ทันที หลังจากนั้นเว็บไซต์ก็แพร่หลายมาก ขอแปะลิงก์คำตอบไว้เป็นข้อมูลอ้างอิง stackoverflow link
แม้จะไม่เกี่ยวกับ Flask แต่ผมไม่ชอบโลโก้ Flask ใหม่เลย โลโก้เก่ามีความวินเทจและให้ความรู้สึกเหมือนงานทำมือ แต่โลโก้ใหม่เหมือนงานที่นักเรียนมัธยมทำเล่นด้วย WordArt มากกว่า โลโก้เก่า, โลโก้ใหม่
ขอถามหน่อยว่าเว็บไซต์ที่คุณสร้างคือ yout.com หรือเปล่า และยังใช้ Flask อยู่ไหม
ถ้าได้เห็น microphonetest.com กลับมามีชีวิตอีกครั้งด้วย vibe coding สักรอบก็คงดีมาก
ไม่แนะนำให้เขียนเบนช์มาร์กแบบวัดเวลาแล้วสะสมภายในลูป ควรวัดเวลาการทำงานของลูปทั้งหมดแล้วหารด้วยจำนวนรอบ เพราะ jitter ที่เกิดจากการวัดเวลาเองอาจทำให้ผลลัพธ์เพี้ยนได้
timeitในไลบรารีมาตรฐาน timeit docsกังวลว่า Python จะถูกตรึงเหมือน TeX ที่เวอร์ชัน 3.14 ลิงก์ Reddit
พอเห็นความเห็นที่บอกว่าหวังว่าจะไม่ “หยุด” ก็รู้สึกสดใหม่ดี เพราะมันสะท้อนว่า Donald Knuth ให้ความสำคัญกับระบบที่ให้ผลลัพธ์เดิมอย่างต่อเนื่องมากกว่าการเปลี่ยนแปลง ในโลกที่ทุกอย่างดูล้าสมัยในไม่กี่ปี ความหมกมุ่นว่าพอมี OOO ใหม่ออกมาแล้วต้องรีบเปลี่ยนทันทีนั้นดูเหมือนอาการป่วย เราไม่มีเหตุผลเลยที่จะเขียนโค้ดที่ใช้ได้ 100 ปีไม่ได้ ท้ายที่สุดแล้วโค้ดก็คือคณิตศาสตร์ เหมือนกับที่ไม่มีใครถูกมองว่าเชยเพียงเพราะใช้พหุนามที่ถูกคิดค้นมาหลายพันปีก่อน ผมคิดว่าการยึดอยู่กับสิ่งที่พิสูจน์แล้วก็เป็นท่าทีที่จำเป็น ไม่จำเป็นต้องหมกมุ่นกับเวอร์ชันใหม่หรือเครื่องมือใหม่ตลอดเวลา คนที่เขียนโค้ดที่ไม่จำเป็นต้องเปลี่ยนต่างหากที่มีส่วนช่วยจริง ๆ
มีคอมเมนต์ว่ามันเข้ากับมุก πthon ได้อย่างน่าประหลาดใจ
ทุกครั้งที่มีข่าว Python ก็ยังเสียดายที่แม้จะเป็นปี 2025 แล้ว PyPy ก็ยังคงเดินเป็นสายแยกอยู่ สงสัยว่า someday Python แบบไม่มี GIL จะไปถึงจุดที่มี C FFI แบบไม่มี GIL ได้ด้วยหรือไม่ คิดว่านั่นจะช่วย Python ได้มากจริง ๆ
C FFI สามารถปลด GIL ด้วยตนเองได้มานานแล้ว เลยอยากรู้ว่าคำพูดนี้หมายถึงอะไรอย่างเจาะจง
ผมคิดว่าการที่เริ่มจากภาษา C แล้วมีคอมไพเลอร์หลายตัวจนเกิดภาษาถิ่นหลายแบบเป็นระบบนิเวศที่ดีต่อสุขภาพ เพราะมันกระตุ้นการทดลองและการพัฒนา ผมมองว่าความต่างระหว่าง PyPy กับ CPython ก็ไม่ได้มาก และยังเข้ากันได้สูง คู่มือความเข้ากันได้ของ pypy
freethreading นั่นแหละคือเป้าหมายนี้ เท่าที่รู้ยังมีไลบรารี C FFI หลายตัวที่ยังไม่ถูกปรับให้ทำงานได้โดยไม่มี GIL จึงยังใช้ freethreading เป็นค่าปริยายไม่ได้
Python ได้เพิ่ม JIT แบบทดลองเข้ามา ทำให้ขยับเข้าใกล้ PyPy ขึ้นอีกก้าว ต่อจากนี้จะสร้าง JIT ใหม่เองหรือจะรวม PyPy เข้าไปก็ไม่รู้ แต่เชื่อว่าได้เรียนรู้อะไรจาก PyPy มาเยอะ
อยากถามว่าคุณคิดไหมว่าเรื่องแบบนี้ (การรวมระบบการติดตั้งใช้งานที่แยกกันอยู่) อาจเปลี่ยนได้ ถ้า Python เผลอนำ breaking change อีกแบบที่กระทบประสิทธิภาพเข้าไปโดยไม่ตั้งใจ มันจะสร้างผลเสียให้ผู้ใช้ในวงกว้าง องค์กร Python จะต้องการสิ่งนั้นจริงหรือ
น่าสนใจที่ PyPy ยังเร็วกว่า free threaded CPython แม้ในโค้ดแบบมัลติเธรด
สิ่งที่สะดุดตาคือการเปลี่ยนผ่านไปสู่ non-GIL เป็นไปอย่างราบรื่นมาก เมื่อเทียบกับตอนเปลี่ยนจาก 2 ไป 3 ครั้งนี้ยอดเยี่ยมจริง ๆ การที่ประสิทธิภาพขึ้นมาใกล้มาตรฐานได้เร็วมากก็น่าตื่นเต้น และหวังว่าส่วนที่ยังไม่เข้ากันก็คงจะหายไปในไม่ช้า
ถ้าอยากลองรันเบนช์มาร์กเองแบบเร็ว ๆ ขอแนะนำรีโป fast_langton_ant รันด้วยคำสั่งประมาณ
python3 server.py -s 10000000 -nสงสัยว่าฟีเจอร์คอมเมนต์แบบพับได้ (fold comment) ถูกใช้ตาม karma หรือเงื่อนไขอื่นหรือไม่ เรื่องที่ Miguel เข้ามาช่วยเป็นโพสต์ยอดนิยมที่สุดจึงน่าประทับใจ แต่พออยากดูเฉพาะเรื่องที่เกี่ยวกับเนื้อหาหลัก ก็เพิ่งสังเกตเป็นครั้งแรกว่าไม่มีฟังก์ชันพับคอมเมนต์
ผมคิดว่าใช้เบนช์มาร์กที่มีแค่ลูปธรรมดากับการคำนวณจำนวนเต็มเพื่อประเมินการใช้งาน Python ในโลกจริงนั้นค่อนข้างฝืน การจัดการแฮชแมปหรือสตริงน่าจะใกล้กับโค้ดจริงมากกว่า ผู้ใช้ Python จำนวนมากก็ปล่อยให้การคำนวณเชิงตัวเลขเป็นหน้าที่ของไลบรารีภายนอก
เบนช์มาร์กทุกตัวล้วนถูกออกแบบมาเพื่อวัดตามเกณฑ์บางอย่างอยู่แล้ว ผู้เขียนได้อธิบายเป้าหมายไว้ในบทความ ถ้าสนใจก็แนะนำให้อ่าน
ผมเองก็อยากให้เป็นบทวิเคราะห์ที่ละเอียดกว่านี้ แต่ถึงอย่างนั้นเบนช์มาร์กแบบนี้ก็ตรงกับการใช้งานจริงของผมมากกว่า ของผมส่วนใหญ่คือสร้าง Monte Carlo simulation หรือการคำนวณทางวิทยาศาสตร์ง่าย ๆ ซ้ำ ๆ กับปัญหาหลากหลายแบบ สำหรับซิมูเลชันใช้ครั้งเดียวผมไม่จำเป็นต้องใช้ทั้งอัลกอริทึมเร็วหรือไลบรารีที่ไม่คุ้นเคย บางครั้งใช้เวลา 10 นาทีก็ไม่เป็นไร (เช่น
scipy,numpyก็ใช้เป็นหลักอยู่แล้ว) เพราะผมเปลี่ยนสมมติฐานในการรันซ้ำบ่อยมาก จึงพยายามทำให้เรียบง่ายที่สุด ความอ่านง่ายและโค้ดแบบเขียนสดสำคัญกว่า และไม่เป็นไรถ้าจะยังไม่ค่อยได้ปรับแต่งประสิทธิภาพ (เช่น Fibonacci, bubble sort, nested for loop) ถ้าต้องการประสิทธิภาพจริง ๆ ค่อยไปเขียนส่วนสำคัญเองด้วย cpp/zmp/pybind/numbaการใส่ตัวอย่างยอดนิยมอย่างการเรียก FastAPI endpoint หรือการคำนวณด้วย numpy ลงในเบนช์มาร์ก น่าจะใกล้กับการใช้งาน Python ในโลกจริงมากกว่า แม้ส่วนเหล่านี้อาจไม่ใช่ pure python code แต่ในความเป็นจริงคนจำนวนมากก็ใช้ Python แบบนั้น
สงสัยว่าการทำเบนช์มาร์กด้วยแค่ tight loop และการคำนวณ int จะสมจริงแค่ไหน
สงสัยว่า tail call interpreter แบบทดลองใหม่ (ออปชัน
--with-tail-call-interp) ถูกนำไปรวมในเบนช์มาร์กหรือไม่ เอกสารทางการของ tail-call-interp เนื่องจากในผลทดสอบไม่ได้พูดถึง เลยเดาว่าน่าจะไม่ได้รวมไว้ อยากเห็นการเปรียบเทียบว่า tail call interpreter ต่างจากตัวอื่นที่มีอยู่เดิมมากแค่ไหน--with-tail-call-interp) ไม่แน่ใจว่าการปรับแต่งนั้นใช้กับ recursive tail call ด้วยหรือไม่ แต่ถ้าใช้ก็น่าจะเห็นประสิทธิภาพดีขึ้นในเทสต์ Fibonacci