- อินเทอร์พรีเตอร์แบบ tail-calling ของ CPython แสดงประสิทธิภาพเร็วกว่าแบบเดิมราว 15% ในสภาพแวดล้อม Windows x86-64
- บน macOS AArch64 (XCode Clang) ก็ยืนยันได้ว่ามีประสิทธิภาพดีขึ้นราว 5% และบน Windows ใช้ความสามารถเชิงทดลองของ MSVC 2026
- ในเบนช์มาร์ก pyperformance การทดสอบส่วนใหญ่มีความเร็วเพิ่มขึ้น และบางรายการดีขึ้นสูงสุดถึง 78%
- สาเหตุหลักของประสิทธิภาพที่ดีขึ้นวิเคราะห์ได้ว่าเกิดจาก การรีเซ็ต optimization heuristic ของคอมไพเลอร์และการปรับปรุง inlining
- เมื่อ Python 3.15 ออกรุ่นจริง จะมีการเปิดใช้เป็นค่าเริ่มต้นกับบิลด์ที่อิง Visual Studio 2026
การปรับปรุงประสิทธิภาพของอินเทอร์พรีเตอร์แบบ tail-calling
- วัดได้ว่า อินเทอร์พรีเตอร์แบบ tail-calling ของ CPython เร็วกว่า อินเทอร์พรีเตอร์แบบ switch-case เดิมราว 15% บน Windows x86-64
- อ้างอิงจาก pyperformance ค่าเฉลี่ยเรขาคณิตดีขึ้น 15~16%
- บางเบนช์มาร์กเร็วขึ้นสูงสุด 78% ขณะที่มีเพียงไม่กี่กรณีที่ช้าลง 60%
- บน macOS AArch64 (XCode Clang) ยืนยันได้ว่าประสิทธิภาพดีขึ้นราว 5%
- ผลลัพธ์นี้ใช้ได้ภายใต้สมมติฐานว่าไม่มีการเปลี่ยนแปลงระหว่างรอบการพัฒนา Python 3.15
เปรียบเทียบโครงสร้างของอินเทอร์พรีเตอร์
- วิธีการสร้างอินเทอร์พรีเตอร์ด้วย C แบ่งได้เป็น 3 แบบคือ switch-case, computed goto, และ tail-call threaded
- switch-case: จัดการการแตกแขนงตามคำสั่งแต่ละตัว
- computed goto: ส่วนขยายของ GCC/Clang ที่กระโดดไปยังที่อยู่ของสาขาโดยตรง
- tail-call threaded: แยกตัวจัดการไบต์โค้ดแต่ละตัวเป็นฟังก์ชัน แล้วทำ tail call ไปยังฟังก์ชันถัดไป
- ในอดีต C compiler ไม่ได้รับประกันการทำ tail call optimization จึงมีความเสี่ยงเรื่อง stack overflow
- ด้วยแอตทริบิวต์
__attribute__((musttail)) ของ Clang และ [[msvc::musttail]] ของ MSVC จึงสามารถบังคับใช้ tail call ได้
ผลการบิลด์ด้วย MSVC 2026 สำหรับ Windows
- ในการบิลด์ CPython ที่ใช้ความสามารถเชิงทดลองของ MSVC เบนช์มาร์กส่วนใหญ่มีความเร็วเพิ่มขึ้น
- ตัวอย่างผลลัพธ์:
spectralnorm: 1.48 เท่า
nbody: 1.35 เท่า
bm_django_template: 1.18 เท่า
xdsl: 1.14 เท่า
- มีการสะท้อนข้อมูลนี้อย่างเป็นทางการในเอกสาร “What’s New” ของ Python 3.15
- สามารถใช้งาน อินเทอร์พรีเตอร์แบบ tail-calling ได้ในบิลด์ Visual Studio 2026 (MSVC 18)
- ไลบรารี Python ล้วนเร็วขึ้นราว 15% และสคริปต์ขนาดเล็กเร็วขึ้นได้สูงสุด 40%
สาเหตุของประสิทธิภาพที่ดีขึ้น
- การทำ tail-calling ช่วย รีเซ็ต optimization heuristic ของคอมไพเลอร์ และทำให้เกิดการสร้างโค้ดที่มีประสิทธิภาพมากขึ้น
- ลูปอินเทอร์พรีเตอร์เดิมของ CPython ประกอบด้วยฟังก์ชันเดียวราว 12,000 บรรทัด ทำให้ การเพิ่มประสิทธิภาพแบบ inlining ล้มเหลวบ่อยครั้ง
- มีหลายกรณีที่คอมไพเลอร์ปฏิเสธการ inlining เพื่อหลีกเลี่ยงการเพิ่มขนาดโค้ด
- ในแบบ tail-calling ฟังก์ชันถูกแยกออก ทำให้ ฟังก์ชันเรียบง่ายสามารถถูก inline ได้
- ตัวอย่างเช่น ฟังก์ชันง่าย ๆ อย่าง
PyStackRef_CLOSE_SPECIALIZED ถูก inline
- มีรายงานปรากฏการณ์เดียวกันนี้แม้ในบิลด์แบบ PGO (profile-guided optimization)
วิธีบิลด์และการใช้งาน
- ขณะนี้ ยังบิลด์จากซอร์สได้เท่านั้น
- ในอนาคตเมื่อการพัฒนา Python 3.15 มีเสถียรภาพ จะมีการแจกจ่ายไบนารีอย่างเป็นทางการ
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
เป็นตัวอย่างที่แสดงความต่างของการกำหนดแอตทริบิวต์
musttailและpreserve_noneระหว่าง MSVC กับ Clangแอตทริบิวต์เหล่านี้ต้องติดกับตัวประกาศฟังก์ชัน และจะไม่ทำงานหากวางไว้ในตำแหน่งตัวระบุฟังก์ชัน
ลิงก์โค้ดที่เกี่ยวข้อง
น้ำเสียงเหมือนจะสื่อว่า Microsoft บอกเรื่องฟีเจอร์ที่ไม่เปิดเผยสู่สาธารณะแบบนี้เฉพาะกับโปรเจกต์ที่มองว่าสำคัญ
[[msvc::musttail]]จริง ๆ แล้วเป็นแอตทริบิวต์ที่มีเอกสารทางการจะไปแก้บทความบล็อกให้สะท้อนเรื่องนี้
คอมเมนต์ HN ที่เกี่ยวข้อง
พออ่านแล้วก็เห็นว่าแนวทางนี้ให้ความสำคัญกับความโปร่งใสและฟีดแบ็กที่รวดเร็ว เลยคิดว่าน่าเชื่อถือ
ถ้ามีการตรวจสอบด้วยคอมไพเลอร์ข้ามชุดหรือมีการตรวจสอบอิสระก็จะยิ่งดี แต่ก็มองว่าน่าเชื่อถือได้เพราะผู้เขียนเปิดเผยอย่างโปร่งใสเต็มที่
เพราะเปิดเผยตั้งแต่เนิ่น ๆ Nelson เลยพบบั๊กของ Clang 19 และแก้ได้ก่อนออกรีลีสจริง
ครั้งนี้มั่นใจกว่าเพราะมีการปรับปรุงสองอย่างคือ dispatch logic และ inlining
MSVC สามารถแปลง switch-case interpreter ให้เป็น threaded code ได้ในบางเงื่อนไข แต่ CPython ซับซ้อนเกินไปจนใช้การปรับแต่งนั้นไม่ได้
แทนที่จะเป็นแบบนั้น แนวทาง tail call ทำให้คนเขียนโค้ด C ควบคุมได้มากกว่า
อ้างอิงที่เกี่ยวข้อง: เงื่อนไข threaded code ของ MSVC, issue ที่เกี่ยวกับ forceinline
ก่อนหน้านี้ optimization อย่าง tail duplication อาจเกิดหรือไม่เกิดตามการตัดสินใจของคอมไพเลอร์ แต่ตอนนี้อินเทอร์พรีเตอร์สามารถแสดงรูปแบบ machine code ที่ต้องการได้โดยตรง
ลิงก์การอภิปรายก่อนหน้า
เลือก Python เพราะecosystem ของ VS หนักเกินไปเมื่อเทียบกับ C#/MAUI
Tkinter ใช้งานไม่ถนัด ส่วน Qt ก็มีภาระในการเรียนรู้สูง เลยใช้คู่ wxGlade + wxPython
ต้องการแค่ dependency เดียวที่ติดตั้งผ่าน pip ได้ และชอบความรู้สึกแบบ Pythonicในการใช้งาน
เลยยินดีกับการปรับปรุง runtime บน Windows
ทำ UI ได้เร็วด้วย QtCreator แล้วค่อยต่อ logic ด้วย Python ทำให้พัฒนาได้เร็วมาก
ไม่ใช่แบบ retained mode อย่าง Tkinter หรือ Qt แต่เป็นแนว immediate mode เลยเหมาะมากกับเครื่องมือภายใน
โปรเจกต์ imgui_bundle
บอกว่าคิดไว้ว่าน่าจะถูกเขียนเป็นแอสเซมบลีแยกตาม ISA หลัก ๆ ไปแล้ว
[[msvc::musttail]]เป็นแอตทริบิวต์ใหม่มากที่เพิ่งเพิ่มเข้ามาใน MSVC 14.50 (ออกเมื่อเดือนที่แล้ว) และทีม CPython ก็ใช้มันเพิ่มประสิทธิภาพได้ภายในไม่กี่สัปดาห์เอกสาร MSVC musttail
Guido ให้ความสำคัญกับความเรียบง่ายของโค้ด ทำให้การนำ JIT เข้ามาช้า และต่อมาจึงมีความพยายามอย่าง PEP 744 (JIT Compilation)
การ optimize ระดับแอสเซมบลีเป็นฝันร้ายด้านการบำรุงรักษา และคอขวดที่แท้จริงของ Python คือระบบแพ็กเกจ
PyPy เร็วเพราะมี JIT แต่เข้ากันไม่ได้กับ C extension
โมเดลเธรดของ Python ก็ทำให้การ optimize ยากขึ้น
ขณะที่ JS เป็น single-thread จึงง่ายกว่า
Python ยังมีทางอ้อมไปใช้ C extension ได้ จึงมีแรงกดดันน้อยกว่าที่จะต้อง optimize ตัว CPython เอง
อีกทั้ง CPython ยังติดข้อจำกัดเรื่องecosystem ของ C extensionขนาดใหญ่ จึงทำลายความเข้ากันได้ไม่ได้
ส่วน V8 เปลี่ยนโครงสร้างภายในได้อย่างอิสระกว่า
และยังต้องรักษา C ABI ที่เสถียร ทำให้ JIT วิเคราะห์โค้ดได้ไม่อิสระนัก
มีการยกตัวอย่างว่า PyPy ก็ต้องลำบากมากในการรองรับข้อจำกัดเหล่านี้
อีกทั้ง JS รองรับแค่ JS ล้วนก็พอ แต่ Python ต้องรักษา ecosystem ของ extension ภายนอกไว้ จึงมีข้อจำกัดในการ optimize มากกว่า
พร้อมแชร์ว่าตัวเองเคยใช้
mitataวัดประสิทธิภาพไลบรารี JS มาก่อนPR การ optimize ของ Immer JS
คำอธิบายใน Wikipedia, ตัวอย่างของ Matplotlib
มันแสดงการกระจายแบบสมมาตร แต่ก็มีเสียงวิจารณ์ว่าการทำ smoothing อาจบิดเบือนการกระจายจริงและเปลืองพื้นที่
ใน การอภิปรายบน HN ก็มีความเห็นว่า half-violin plot ดีกว่า
ภาพตัวอย่าง
พร้อมล้อเลียนลักษณะเด่นของข้อความจาก AI เช่นย่อหน้าสั้น น้ำเสียงเชิงบวกเกินไป และเนื้อหาไม่ลึก