Cinder เป็นเวอร์ชันที่ใช้งานจริงที่เน้นประสิทธิภาพภายในของ Meta ของ CPython 3.10 ประกอบด้วยการเพิ่มประสิทธิภาพการทำงานหลายประการ รวมถึงการแคชแบบอินไลน์ของ bytecode, การประเมิน coroutines อย่างกระตือรือร้น, JIT วิธีการในแต่ละครั้ง และคอมไพเลอร์ bytecode รุ่นทดลองที่ใช้คำอธิบายประกอบประเภทเพื่อปล่อย bytecode เฉพาะประเภทซึ่งทำงานได้ดีขึ้นใน JIT
Cinder กำลังขับเคลื่อน Instagram ซึ่งเป็นจุดเริ่มต้น และมีการใช้มากขึ้นเรื่อยๆ ในแอปพลิเคชัน Python ใน Meta
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ CPython โปรดดูที่ README.cpython.rst
คำตอบสั้น ๆ : ไม่
เราได้เผยแพร่ Cinder สู่สาธารณะเพื่ออำนวยความสะดวกในการสนทนาเกี่ยวกับการอัปสตรีมงานนี้บางส่วนไปยัง CPython และเพื่อลดความซ้ำซ้อนของความพยายามในหมู่คนที่ทำงานเกี่ยวกับประสิทธิภาพของ CPython
ถ่านไม่ได้ขัดเงาหรือจัดทำเป็นเอกสารเพื่อการใช้งานของผู้อื่น เราไม่ต้องการให้มันเป็นทางเลือกแทน CPython เป้าหมายของเราในการทำให้โค้ดนี้พร้อมใช้งานคือ CPython ที่เร็วขึ้นแบบครบวงจร ดังนั้นในขณะที่เราใช้งาน Cinder ในการผลิต แต่ถ้าคุณเลือกที่จะดำเนินการดังกล่าว คุณก็ดำเนินการได้ด้วยตัวเอง เราไม่สามารถมุ่งมั่นที่จะแก้ไขรายงานข้อผิดพลาดภายนอกหรือตรวจสอบคำขอดึงข้อมูลได้ เราตรวจสอบให้แน่ใจว่า Cinder มีความเสถียรและรวดเร็วเพียงพอสำหรับปริมาณงานการผลิตของเรา แต่เราไม่รับประกันความเสถียรหรือความถูกต้องหรือประสิทธิภาพสำหรับปริมาณงานภายนอกหรือกรณีการใช้งานใดๆ
ดังที่กล่าวไว้ หากคุณมีประสบการณ์รันไทม์ภาษาไดนามิกและมีแนวคิดที่จะทำให้ Cinder เร็วขึ้น หรือหากคุณทำงานกับ CPython และต้องการใช้ Cinder เป็นแรงบันดาลใจในการปรับปรุง CPython (หรือช่วยตั้งแต่ต้นทางของ Cinder ไปจนถึง CPython) โปรดติดต่อ เราอยากจะแชท!
Cinder ควรสร้างเหมือนกับ CPython configure
และ make -j
อย่างไรก็ตาม เนื่องจากการพัฒนาและการใช้งาน Cinder ส่วนใหญ่เกิดขึ้นในบริบทที่เฉพาะเจาะจงของ Meta เราจึงไม่ค่อยได้ใช้มันมากนักในสภาพแวดล้อมอื่นๆ ด้วยเหตุนี้ วิธีที่น่าเชื่อถือที่สุดในการสร้างและรัน Cinder คือการใช้การตั้งค่าแบบ Docker จากเวิร์กโฟลว์ GitHub CI ของเราอีกครั้ง
หากคุณเพียงต้องการได้ Cinder ที่ใช้งานได้โดยไม่ต้องสร้างมันขึ้นมาเอง Runtime Docker Image ของเราจะเป็นวิธีที่ง่ายที่สุด (ไม่จำเป็นต้องมีโคลน repo!):
docker run -it --rm ghcr.io/facebookincubator/cinder-runtime:cinder-3.10
หากคุณต้องการสร้างมันขึ้นมาเอง:
git clone https://github.com/facebookincubator/cinder
docker run -v "$PWD/cinder:/vol" -w /vol -it --rm ghcr.io/facebookincubator/cinder/python-build-env:latest bash
./configure && make
โปรดทราบว่า Cinder สร้างหรือทดสอบบน Linux x64 เท่านั้น สิ่งอื่นใด (รวมถึง macOS) อาจจะไม่ทำงาน อิมเมจ Docker ด้านบนใช้ Fedora Linux และสร้างจากไฟล์ข้อมูลจำเพาะ Docker ใน Cinder repo: .github/workflows/python-build-env/Dockerfile
มีเป้าหมายทดสอบใหม่ๆ ที่อาจน่าสนใจ make testcinder
นั้นค่อนข้างจะเหมือนกับ make test
ยกเว้นว่ามันจะข้ามการทดสอบบางอย่างที่เป็นปัญหาในสภาพแวดล้อม dev ของเรา make testcinder_jit
รันชุดทดสอบโดยเปิดใช้งาน JIT อย่างสมบูรณ์ ดังนั้นฟังก์ชันทั้งหมดจึงถูก JIT'ed make testruntime
รันชุดการทดสอบหน่วย C++ gtest สำหรับ JIT และ make test_strict_module
รันชุดทดสอบสำหรับโมดูลที่เข้มงวด (ดูด้านล่าง)
โปรดทราบว่าขั้นตอนเหล่านี้จะสร้างไบนารี Cinder Python โดยไม่เปิดใช้งานการปรับให้เหมาะสม PGO/LTO ดังนั้นอย่าคาดหวังว่าจะใช้คำแนะนำเหล่านี้เพื่อเร่งความเร็วให้กับปริมาณงาน Python ใดๆ
Cinder Explorer คือพื้นที่เล่นสด ซึ่งคุณจะได้เห็นว่า Cinder คอมไพล์โค้ด Python จากซอร์สหนึ่งไปยังอีกแอสเซมบลีได้อย่างไร คุณสามารถทดลองใช้ได้! รู้สึกอิสระที่จะยื่นคำขอคุณสมบัติและรายงานข้อผิดพลาด โปรดทราบว่า Cinder Explorer ก็เหมือนกับส่วนที่เหลือของสิ่งนี้ "ได้รับการสนับสนุน" บนพื้นฐานความพยายามอย่างดีที่สุด
Instagram ใช้สถาปัตยกรรมเว็บเซิร์ฟเวอร์แบบหลายกระบวนการ กระบวนการหลักเริ่มต้น ดำเนินการเริ่มต้น (เช่น การโหลดโค้ด) และแยกกระบวนการของผู้ปฏิบัติงานนับสิบเพื่อจัดการกับคำขอของไคลเอ็นต์ กระบวนการของผู้ปฏิบัติงานจะเริ่มต้นใหม่เป็นระยะๆ ด้วยเหตุผลหลายประการ (เช่น หน่วยความจำรั่ว การใช้โค้ด) และมีอายุการใช้งานค่อนข้างสั้น ในแบบจำลองนี้ ระบบปฏิบัติการจะต้องคัดลอกทั้งเพจที่มีออบเจ็กต์ที่ได้รับการจัดสรรในกระบวนการหลักเมื่อมีการแก้ไขจำนวนการอ้างอิงของออบเจ็กต์ ในทางปฏิบัติ อ็อบเจ็กต์ที่ถูกจัดสรรในกระบวนการหลักมีอายุยืนยาวกว่าผู้ปฏิบัติงาน งานทั้งหมดที่เกี่ยวข้องกับการนับการอ้างอิงนั้นไม่จำเป็น
Instagram มีฐานโค้ด Python ขนาดใหญ่มากและค่าใช้จ่ายเนื่องจากการคัดลอกเมื่อเขียนจากการนับการอ้างอิงนับวัตถุที่มีอายุยืนยาวกลายเป็นเรื่องสำคัญ เราได้พัฒนาโซลูชันที่เรียกว่า "อินสแตนซ์อมตะ" เพื่อให้มีวิธีในการเลือกไม่ใช้ออบเจ็กต์จากการนับการอ้างอิง ดูรวม/object.hสำหรับรายละเอียด คุณสมบัตินี้ควบคุมโดยการกำหนด Py_IMMORTAL_INSTANCES และเปิดใช้งานตามค่าเริ่มต้นใน Cinder นี่เป็นชัยชนะครั้งใหญ่สำหรับเราในการผลิต (~ 5%) แต่มันทำให้โค้ดแบบเส้นตรงช้าลง การดำเนินการตรวจนับการอ้างอิงเกิดขึ้นบ่อยครั้ง และต้องตรวจสอบว่าวัตถุมีส่วนร่วมในการตรวจนับอ้างอิงหรือไม่ เมื่อเปิดใช้งานคุณลักษณะนี้
"Shadowcode" หรือ "shadow bytecode" คือการใช้งานล่ามที่เชี่ยวชาญของเรา โดยจะสังเกตกรณีที่ปรับให้เหมาะสมโดยเฉพาะในการดำเนินการของ Python opcodes ทั่วไป และ (สำหรับฟังก์ชันฮอต) จะแทนที่ opcodes เหล่านั้นด้วยเวอร์ชันพิเศษแบบไดนามิก แกนหลักของ shadowcode อยู่ใน Shadowcode/shadowcode.c
แม้ว่าการใช้งานสำหรับไบต์โค้ดเฉพาะนั้นจะอยู่ใน Python/ceval.c
พร้อมกับส่วนที่เหลือของ eval loop การทดสอบเฉพาะ Shadowcode อยู่ใน Lib/test/test_shadowcode.py
มีความคล้ายคลึงกับ Specializing Adaptive Interpreter (PEP-659) ที่จะรวมอยู่ใน CPython 3.11
เซิร์ฟเวอร์ Instagram เป็นปริมาณงานที่มีปริมาณงานมากแบบอะซิงโครนัส โดยแต่ละคำขอของเว็บอาจทริกเกอร์งานอะซิงก์นับแสนงาน ซึ่งหลายรายการสามารถดำเนินการให้เสร็จสิ้นได้โดยไม่มีการระงับ (เช่น ด้วยค่าที่บันทึกไว้)
เราขยายโปรโตคอล vectorcall เพื่อส่งแฟล็กใหม่ Ci_Py_AWAITED_CALL_MARKER
ซึ่งระบุว่าผู้โทรกำลังรอสายนี้ทันที
เมื่อใช้ร่วมกับการเรียกฟังก์ชันอะซิงก์ที่รอทันที เราสามารถประเมินฟังก์ชันที่ถูกเรียกได้ทันที (อย่างกระตือรือร้น) จนถึงเสร็จสมบูรณ์ หรือจนถึงการระงับครั้งแรก หากฟังก์ชันเสร็จสมบูรณ์โดยไม่ถูกระงับ เราจะสามารถคืนค่าได้ทันที โดยไม่มีการจัดสรรฮีปเพิ่มเติม
เมื่อใช้กับการรวบรวมแบบอะซิงโครนัส เราสามารถประเมินชุดของสิ่งที่รอคอยที่ส่งผ่านได้ทันที (อย่างกระตือรือร้น) ซึ่งอาจหลีกเลี่ยงค่าใช้จ่ายในการสร้างและการกำหนดเวลาของงานหลายอย่างสำหรับโครูทีนที่สามารถทำให้เสร็จพร้อมกัน อนาคตที่เสร็จสมบูรณ์ ค่าที่บันทึกไว้ ฯลฯ
การเพิ่มประสิทธิภาพเหล่านี้ส่งผลให้เกิดการปรับปรุงประสิทธิภาพของ CPU อย่างมีนัยสำคัญ (~ 5%)
สิ่งนี้ส่วนใหญ่จะนำไปใช้ใน Python/ceval.c
ผ่านทางแฟล็ก vectorcall ใหม่ Ci_Py_AWAITED_CALL_MARKER
ซึ่งระบุว่าผู้โทรกำลังรอสายนี้ทันที ค้นหาการใช้มาโคร IS_AWAITED()
และค่าสถานะ vectorcall นี้
Cinder JIT เป็น JIT แบบกำหนดเองตามวิธีการที่ใช้งานใน C++ เปิดใช้งานผ่านแฟล็ก -X jit
หรือตัวแปรสภาพแวดล้อม PYTHONJIT=1
รองรับ opcode ของ Python เกือบทั้งหมด และสามารถบรรลุการปรับปรุงความเร็ว 1.5-4x บนการวัดประสิทธิภาพ Python จำนวนมาก
ตามค่าเริ่มต้นเมื่อเปิดใช้งาน JIT จะคอมไพล์ทุกฟังก์ชันที่เคยเรียกใช้ ซึ่งอาจทำให้โปรแกรมของคุณช้าลง ไม่เร็วขึ้น เนื่องจากโอเวอร์เฮดของฟังก์ชันที่ไม่ค่อยเรียกว่าการคอมไพล์ด้วย JIT ตัวเลือก -X jit-list-file=/path/to/jitlist.txt
หรือ PYTHONJITLISTFILE=/path/to/jitlist.txt
สามารถชี้ไปที่ไฟล์ข้อความที่มีชื่อฟังก์ชันแบบเต็ม (ในรูปแบบ path.to.module:funcname
หรือ path.to.module:ClassName.method_name
) หนึ่งรายการต่อบรรทัด ซึ่งควรคอมไพล์ด้วย JIT เราใช้ตัวเลือกนี้เพื่อรวบรวมเฉพาะชุดฟังก์ชันยอดนิยมที่ได้มาจากข้อมูลโปรไฟล์การผลิต (แนวทางทั่วไปสำหรับ JIT คือการคอมไพล์ฟังก์ชันแบบไดนามิกตามที่สังเกตเห็นว่ามีการเรียกใช้บ่อยครั้ง ยังไม่คุ้มค่าสำหรับเราที่จะใช้สิ่งนี้ เนื่องจากสถาปัตยกรรมการผลิตของเราเป็นเว็บเซิร์ฟเวอร์แบบ pre-fork และสำหรับ เหตุผลที่แบ่งปันหน่วยความจำเราต้องการทำการคอมไพล์ JIT ทั้งหมดล่วงหน้าในกระบวนการเริ่มต้นก่อนที่ผู้ปฏิบัติงานจะถูกแยกออก ซึ่งหมายความว่าเราไม่สามารถสังเกตปริมาณงานในกระบวนการก่อนที่จะตัดสินใจว่าฟังก์ชันใดที่จะคอมไพล์ JIT)
JIT อยู่ในไดเร็กทอรี Jit/
และการทดสอบ C++ ของมันอยู่ใน RuntimeTests/
(รันสิ่งเหล่านี้ด้วย make testruntime
) นอกจากนี้ยังมีการทดสอบ Python บางส่วนใน Lib/test/test_cinderjit.py
; สิ่งเหล่านี้ไม่ได้หมายความว่าจะครอบคลุมทั้งหมด เนื่องจากเรารันชุดทดสอบ CPython ทั้งหมดภายใต้ JIT ผ่าน make testcinder_jit
; ครอบคลุมถึงกรณี Edge ของ JIT ที่ไม่พบในชุดทดสอบ CPython
ดู Jit/pyjit.cpp
สำหรับตัวเลือก -X
อื่นๆ และตัวแปรสภาพแวดล้อมที่มีอิทธิพลต่อพฤติกรรมของ JIT นอกจากนี้ยังมีโมดูล cinderjit
ที่กำหนดไว้ในไฟล์นั้นซึ่งเปิดเผยยูทิลิตี้ JIT บางอย่างกับโค้ด Python (เช่น การบังคับให้ฟังก์ชันเฉพาะทำการคอมไพล์ ตรวจสอบว่าฟังก์ชันถูกคอมไพล์หรือไม่ ปิดการใช้งาน JIT) โปรดทราบว่า cinderjit.disable()
ปิดใช้งานเฉพาะการคอมไพล์ในอนาคตเท่านั้น มันจะรวบรวมฟังก์ชันที่รู้จักทั้งหมดทันทีและเก็บฟังก์ชันที่คอมไพล์ด้วย JIT ที่มีอยู่ไว้
JIT จะลดระดับ Python bytecode ลงเป็นการแสดงระดับกลางระดับสูง (HIR) สิ่งนี้ถูกนำไปใช้ใน Jit/hir/
HIR แมปอย่างใกล้ชิดกับ Python bytecode อย่างใกล้ชิด แม้ว่าจะเป็นเครื่องรีจิสเตอร์แทนที่จะเป็นเครื่องสแต็ก แต่ก็มีระดับที่ต่ำกว่าเล็กน้อย มันถูกพิมพ์ และรายละเอียดบางอย่างที่ถูกบดบังด้วยโค้ดไบต์ Python แต่มีความสำคัญต่อประสิทธิภาพ (โดยเฉพาะอย่างยิ่งการนับอ้างอิง) คือ เปิดเผยอย่างชัดเจนใน HIR HIR ถูกแปลงเป็นรูปแบบ SSA โดยมีการดำเนินการผ่านการปรับให้เหมาะสมบางส่วน จากนั้นการดำเนินการนับการอ้างอิงจะถูกแทรกลงในแบบฟอร์มโดยอัตโนมัติตามข้อมูลเมตาเกี่ยวกับการนับซ้ำและเอฟเฟกต์หน่วยความจำของ opcode ของ HIR
จากนั้น HIR จะถูกลดระดับลงเป็นการแสดงระดับกลางระดับต่ำ (LIR) ซึ่งเป็นนามธรรมเหนือแอสเซมบลี ซึ่งนำไปใช้ใน Jit/lir/
ใน LIR เราทำการจัดสรรการลงทะเบียน การปรับให้เหมาะสมเพิ่มเติมบางอย่างผ่านไป และในที่สุด LIR ก็ถูกลดระดับลงเป็นแอสเซมบลี (ใน Jit/codegen/
) โดยใช้ไลบรารี asmjit ที่ยอดเยี่ยม
JIT อยู่ในช่วงเริ่มต้น แม้ว่าจะสามารถขจัดค่าใช้จ่ายของลูปล่ามได้แล้ว และเสนอการปรับปรุงประสิทธิภาพที่สำคัญสำหรับฟังก์ชันต่างๆ มากมาย แต่เราเพิ่งเริ่มที่จะเริ่มต้นการปรับปรุงประสิทธิภาพที่เป็นไปได้เบื้องต้นเท่านั้น ยังไม่มีการนำการเพิ่มประสิทธิภาพคอมไพเลอร์ทั่วไปหลายอย่างมาใช้ การจัดลำดับความสำคัญของการเพิ่มประสิทธิภาพของเรานั้นส่วนใหญ่ขับเคลื่อนโดยลักษณะของปริมาณงานการผลิต Instagram
โมดูลที่เข้มงวดมีบางสิ่งที่รวมเป็นหนึ่งเดียว:
1. เครื่องวิเคราะห์แบบคงที่ที่สามารถตรวจสอบได้ว่าการรันโค้ดระดับบนสุดของโมดูลจะไม่มีผลข้างเคียงที่มองเห็นได้ภายนอกโมดูลนั้น
2. ประเภท StrictModule
ที่ไม่เปลี่ยนรูปซึ่งใช้แทนประเภทโมดูลเริ่มต้นของ Python
3. ตัวโหลดโมดูล Python ที่สามารถจดจำโมดูลที่เลือกใช้ในโหมดเข้มงวด (ผ่าน import __strict__
ที่ด้านบนของโมดูล) วิเคราะห์โมดูลเหล่านั้นเพื่อตรวจสอบความถูกต้องว่าไม่มีผลข้างเคียงจากการนำเข้า และเติมข้อมูลเหล่านั้นใน sys.modules
เป็นอ็อบเจ็กต์ StrictModule
Static Python เป็นคอมไพเลอร์ bytecode ที่ใช้คำอธิบายประกอบประเภทเพื่อปล่อย Python bytecode ชนิดเฉพาะและตรวจสอบประเภท เมื่อใช้ร่วมกับ Cinder JIT จะสามารถส่งมอบประสิทธิภาพที่คล้ายคลึงกับ MyPyC หรือ Cython ในหลายกรณี ในขณะที่ให้ประสบการณ์นักพัฒนา Python ล้วนๆ (ไวยากรณ์ Python ปกติ ไม่มีขั้นตอนการคอมไพล์เพิ่มเติม) Static Python และ Cinder JIT มีประสิทธิภาพเหนือกว่า CPython หุ้นถึง 18 เท่าในเวอร์ชันพิมพ์ของเกณฑ์มาตรฐาน Richards ที่ Instagram เราใช้ Static Python ในการผลิตเพื่อแทนที่โมดูล Cython ทั้งหมดในโค้ดเบสเว็บเซิร์ฟเวอร์หลักของเราได้สำเร็จ โดยไม่มีการถดถอยด้านประสิทธิภาพ
คอมไพเลอร์ Static Python ถูกสร้างขึ้นบนโมดูล compiler
Python ที่ถูกลบออกจากไลบรารีมาตรฐานใน Python 3 และตั้งแต่นั้นมาก็ได้รับการบำรุงรักษาและอัปเดตจากภายนอก คอมไพเลอร์นี้รวมอยู่ใน Cinder ใน Lib/compiler
คอมไพเลอร์ Static Python ถูกนำมาใช้ใน Lib/compiler/static/
และการทดสอบอยู่ใน Lib/test/test_compiler/test_static.py
คลาสที่กำหนดในโมดูล Static Python จะได้รับสล็อตที่พิมพ์โดยอัตโนมัติ (ขึ้นอยู่กับการตรวจสอบแอตทริบิวต์ของคลาสที่พิมพ์และการมอบหมายคำอธิบายประกอบใน __init__
) และการโหลดแอตทริบิวต์และการจัดเก็บกับอินสแตนซ์ของประเภทเหล่านี้ใช้ opcodes STORE_FIELD
และ LOAD_FIELD
ใหม่ ซึ่งใน JIT จะกลายเป็นโดยตรง โหลด/จัดเก็บจาก/ไปยังหน่วยความจำคงที่ชดเชยในวัตถุ โดยไม่มีทางอ้อมของ LOAD_ATTR
หรือ STORE_ATTR
คลาสยังได้รับ vtables ของวิธีการของพวกเขา เพื่อใช้โดยรหัส INVOKE_*
ที่กล่าวถึงด้านล่าง การสนับสนุนรันไทม์สำหรับคุณลักษณะเหล่านี้อยู่ใน StaticPython/classloader.h
และ StaticPython/classloader.c
ฟังก์ชัน Python แบบคงที่เริ่มต้นด้วยอารัมภบทที่ซ่อนอยู่ ซึ่งจะตรวจสอบว่าประเภทของอาร์กิวเมนต์ที่ให้มาตรงกับคำอธิบายประกอบประเภท และเพิ่ม TypeError
หากไม่เป็นเช่นนั้น การเรียกจากฟังก์ชัน Python แบบคงที่ไปยังฟังก์ชัน Python แบบคงที่อื่นจะข้าม opcode นี้ (เนื่องจากประเภทได้รับการตรวจสอบโดยคอมไพเลอร์แล้ว) การโทรแบบคงที่ถึงแบบคงที่ยังสามารถหลีกเลี่ยงค่าใช้จ่ายในการเรียกใช้ฟังก์ชัน Python ทั่วไปได้มาก เราปล่อยออปโค้ด INVOKE_FUNCTION
หรือ INVOKE_METHOD
ซึ่งมีข้อมูลเมตาเกี่ยวกับฟังก์ชันหรือเมธอดที่ถูกเรียกไปด้วย สิ่งนี้บวกกับโมดูลทางเลือกที่ไม่เปลี่ยนรูป (ผ่าน StrictModule
) และประเภท (ผ่าน cinder.freeze_type()
ซึ่งปัจจุบันเรานำไปใช้กับทุกประเภทในโมดูลที่เข้มงวดและคงที่ในตัวโหลดการนำเข้าของเรา แต่ในอนาคตอาจกลายเป็นส่วนหนึ่งของ Static Python) และคอมไพล์ - ความรู้เวลาของลายเซ็นผู้เรียกช่วยให้เรา (ใน JIT) เปลี่ยนการเรียกใช้ฟังก์ชัน Python จำนวนมากเป็นการเรียกโดยตรงไปยังที่อยู่หน่วยความจำคงที่โดยใช้รูปแบบการโทร x64 โดยมีค่าใช้จ่ายมากกว่าฟังก์ชัน C เล็กน้อย เรียก.
Python แบบคงที่ยังคงค่อยๆ พิมพ์ และรองรับโค้ดที่มีคำอธิบายประกอบเพียงบางส่วนหรือใช้ประเภทที่ไม่รู้จักโดยการถอยกลับไปเป็นพฤติกรรมไดนามิกของ Python ปกติ ในบางกรณี (เช่น เมื่อค่าของประเภทที่ไม่รู้จักแบบคงที่ถูกส่งคืนจากฟังก์ชันที่มีการส่งคืนคำอธิบายประกอบ) opcode CAST
รันไทม์จะถูกแทรก ซึ่งจะทำให้เกิด TypeError
หากประเภทรันไทม์ไม่ตรงกับประเภทที่คาดไว้
Python แบบคงที่ยังรองรับประเภทใหม่สำหรับจำนวนเต็มของเครื่อง บูล คู่ และเวกเตอร์/อาร์เรย์ ใน JIT สิ่งเหล่านี้ได้รับการจัดการเป็นค่าที่ไม่มีกล่อง และเช่น เลขคณิตจำนวนเต็มดั้งเดิมจะหลีกเลี่ยงค่าใช้จ่ายของ Python ทั้งหมด การดำเนินการบางอย่างกับประเภทบิวด์อิน (เช่น รายการหรือตัวห้อยพจนานุกรม หรือ len()
) ก็ได้รับการปรับให้เหมาะสมเช่นกัน
Cinder รองรับการนำโมดูลคงที่ไปใช้ทีละน้อยผ่านตัวโหลดโมดูลแบบเข้มงวด/คงที่ ซึ่งสามารถตรวจจับโมดูลคงที่ได้โดยอัตโนมัติ และโหลดเป็นโมดูลแบบคงที่ด้วยการคอมไพล์ข้ามโมดูล ตัวโหลดจะค้นหาคำอธิบายประกอบ import __static__
และ import __strict__
ที่ด้านบนของไฟล์ และคอมไพล์โมดูลอย่างเหมาะสม หากต้องการเปิดใช้งานตัวโหลด คุณมีหนึ่งในสามตัวเลือก:
1. ติดตั้งตัวโหลดอย่างชัดเจนที่ระดับบนสุดของแอปพลิเคชันของคุณผ่านทาง from cinderx.compiler.strict.loader import install; install()
.
PYTHONINSTALLSTRICTLOADER=1
ในสภาพแวดล้อมของคุณ./python -X install-strict-loader application.py
หรือคุณสามารถคอมไพล์โค้ดทั้งหมดแบบคงที่ได้โดยใช้ ./python -m compiler --static some_module.py
ซึ่งจะคอมไพล์โมดูลเป็น Python แบบคงที่และดำเนินการ
ดู CinderDoc/static_python.rst
สำหรับเอกสารรายละเอียดเพิ่มเติม