Hudson River Trading ( HRT ) ได้ประสบความสำเร็จในการนำ Python fork แบบกำหนดเองมาใช้งานทั่วทั้งองค์กร โดยการใช้งาน lazy imports เพื่อลดเวลาเริ่มต้นของแอปพลิเคชัน Python อย่างมาก ทีมวิศวกรรมของบริษัทเทรดดิ้งแห่งนี้ใช้เวลากว่าสองปีในการพัฒนาและย้ายไปใช้โซลูชันนี้ ซึ่งจะเลื่อนการโหลดโมดูลจนกว่าจะต้องใช้งานจริงในระหว่าง runtime
ปัญหาที่จุดประกายนวัตกรรม
สถาปัตยกรรม monorepo ของ HRT แม้จะช่วยให้ทีมต่างๆ สามารถทำงานร่วมกันได้ แต่กลับสร้างคอขวดด้านประสิทธิภาพที่สำคัญ สคริปต์ Python ของพวกเขากำลัง import โมดูลจำนวนมากมายตอนเริ่มต้น โดยที่หลายๆ imports ไม่เคยถูกใช้งานจริงระหว่างการทำงาน ส่งผลให้เครื่องมือ command-line ใช้เวลาหลายสิบวินาทีในการเริ่มต้น Jupyter notebooks ต้องใช้เวลาหลายนาทีในการโหลด และงาน distributed computing ใช้เวลาในการ import มากกว่าการคำนวณจริง ปัญหานี้รุนแรงเป็นพิเศษเพราะโมดูลของพวกเขามักอยู่ใน distributed file systems และมีโค้ดการเริ่มต้นที่หนัก
การอภิปรายในชุมชนเผยให้เห็นว่านี่ไม่ใช่ปัญหาเฉพาะของ HRT นักพัฒนาหลายคนต่อสู้กับปัญหา import overhead ของ Python โดยเฉพาะใน codebase ขนาดใหญ่ บางคนใช้วิธีแก้ปัญหาชั่วคราวด้วยตนเอง เช่น การวาง imports ไว้ในฟังก์ชันหรือใช้ lazy import libraries ที่มีอยู่ แต่แนวทางเหล่านี้สร้างความท้าทายในการบำรุงรักษาและทำให้โค้ดอ่านยากขึ้น
การปรับปรุงประสิทธิภาพ
- เครื่องมือ command-line: ลดเวลาเริ่มต้นจากหลายสิบวินาทีเป็นเกือบทันที
- Jupyter notebooks: กำจัดความล่าช้าในการ import ที่ใช้เวลา 10-15 นาที
- งานแบบกระจาย: ลดเวลาที่ใช้ในการโหลด dependency ที่ไม่จำเป็นอย่างมีนัยสำคัญ
- โดยรวม: ปรับปรุงเวลาเริ่มต้นได้ 3 เท่า (อิงจากการใช้งานที่คล้ายกัน)
![]() |
---|
กราฟแท่งเทียนที่แสดงการเคลื่อนไหวของราคา สะท้อนบริบททางการเงินที่ HRT ดำเนินงานอยู่และความสำคัญของการ import ที่มีประสิทธิภาพสำหรับกิจกรรมการเทรด |
การใช้งานทางเทคนิคและความท้าทาย
HRT ยืมแนวคิด lazy import จาก Cinder Python fork ของ Meta โดยใช้การปรับเปลี่ยน CPython สองส่วนหลัก แทนที่จะทำ imports ทันที interpreter จะสร้าง placeholder objects ที่เลื่อนการโหลดโมดูลจริงจนกว่าชื่อที่ import จะถูกอ้างอิง แนวทางนี้ทำงานแบบโปร่งใสสำหรับกรณีการใช้งานส่วนใหญ่ แต่มาพร้อมกับข้อจำกัดที่น่าสังเกต
การใช้งานนี้ไม่สามารถจัดการ imports ภายในฟังก์ชันได้เนื่องจากการปรับปรุง local variable ของ Python และ wildcard imports ยังคงเป็นไปไม่ได้ที่จะทำให้ lazy เพราะไม่สามารถกำหนดชื่อที่ export ได้โดยไม่ต้องประเมิน ที่สำคัญกว่านั้น โมดูลที่มี side effects - ที่ปรับเปลี่ยน global state ระหว่าง import - สามารถทำให้เกิดบั๊กที่ละเอียดอ่อนเมื่อการทำงานของพวกเขาถูกเลื่อน
Runtime imports เป็นฝันร้ายในการบำรุงรักษาและสามารถแยกส่วน codebase ได้อย่างรวดเร็ว การวิเคราะห์แบบคงที่ของ imports เป็นสิ่งที่ต้องการมากจนเกือบจะคุ้มค่ากับการสูญเสียประสิทธิภาพการเริ่มต้นเสมอ
ความคิดเห็นนี้เน้นความตึงเครียดหลักในแนวทาง ในขณะที่ lazy imports แก้ปัญหาประสิทธิภาพ แต่อาจทำให้พฤติกรรมของโค้ดคาดเดาได้น้อยลง
ข้อจำกัดทางเทคนิค
- ไม่สามารถทำให้การ import เป็นแบบ lazy ภายในขอบเขตของฟังก์ชันได้
- ไม่รองรับการ import แบบ wildcard (
from module import *
) - โมดูลที่มี side effects ต้องการการจัดการพิเศษ
- การพึ่งพาลำดับของการ import อาจเสียหาย
- การ import แบบ transitive โดยนัยต้องประกาศอย่างชัดเจน
ประสบการณ์การย้ายและบทเรียนที่ได้เรียนรู้
กระบวนการย้ายเผยให้เห็นปัญหาความเข้ากันได้สามประเภทหลัก Import side effects ทำให้เกิดความท้าทายในการดีบั๊กที่ยากที่สุด เนื่องจากการลงทะเบียน decorator และการกำหนดค่าส่วนกลางจะทำงานในเวลาที่ไม่คาดคิดหรือไม่ทำงานเลย การพึ่งพาลำดับ import กลายเป็นปัญหาเมื่อโมดูลที่มี side effects ขัดแย้งกันไม่ได้โหลดตามลำดับที่คาดเดาได้อีกต่อไป นอกจากนี้ implicit transitive imports - ที่โค้ดพึ่งพา submodules ที่ import โดยโมดูลอื่น - เสียหายเมื่อ dependencies เหล่านั้นไม่ได้โหลดจริง
HRT แก้ไขปัญหาเหล่านี้ผ่านการรวมกันของ eager import blocks, exclusion lists สำหรับ third-party packages และการจัดการ dependency แบบชัดเจน บริษัทได้เสร็จสิ้นการย้ายพร้อมกับการอัพเกรด Python 3.12 ทำให้ lazy imports เป็นค่าเริ่มต้นสำหรับโค้ด Python ทั้งหมดภายในไตรมาสที่ 2 ปี 2025
ไทม์ไลน์การย้ายระบบ
- Q1 2023: พัฒนาต้นแบบเริ่มต้นระหว่างการแข่งขัน hackathon ภายในองค์กร
- Q2-Q4 2023: ปรับปรุงการใช้งานและการย้ายทีมงานในช่วงแรก
- Q2 2024: บรรลุความเข้ากันได้แบบ lazy 50% ทั่วทั้ง monorepo
- Q3 2024: เสร็จสิ้นการย้ายไปยัง Python 3.12
- Q2 2025: ปรับใช้ lazy imports เป็นค่าเริ่มต้นทั่วทั้งบริษัท
ผลกระทบต่อประสิทธิภาพและแนวโน้มในอนาคต
ผลลัพธ์ที่ได้มีความสำคัญทั่วระบบนิเวศ Python ของ HRT เครื่องมือ command-line ตอนนี้ให้ feedback ทันทีแทนที่จะมีความล่าช้าในการเริ่มต้นหลายนาที Jupyter notebook workflows ที่เคยต้องใช้เวลา import 10-15 นาทีตอนนี้เริ่มต้นได้เกือบทันที งาน Distributed computing ที่ใช้เวลาโหลด dependencies มากกว่าการทำงานจริงได้เห็นการปรับปรุงประสิทธิภาพอย่างมาก
แม้จะประสบความสำเร็จ HRT ยอมรับภาระการบำรุงรักษาของการดูแล Python fork พวกเขากำลังสำรวจการเสนอ explicit lazy import syntax ให้กับ upstream Python โดยใช้คำสำคัญเช่น lazy import foo แทนที่จะทำให้ laziness เป็นแบบ implicit แนวทางนี้จะแก้ไขความกังวลของ Python Steering Council เกี่ยวกับบั๊กที่ละเอียดอ่อนในขณะที่ทำให้ประโยชน์ด้านประสิทธิภาพพร้อมใช้งานสำหรับชุมชน Python ที่กว้างขึ้น
การอภิปรายรอบการใช้งานของ HRT สะท้อนคำถามที่กว้างขึ้นเกี่ยวกับลักษณะประสิทธิภาพของ Python และการแลกเปลี่ยนระหว่างความสะดวกและความเร็วในการพัฒนาซอฟต์แวร์ขนาดใหญ่
อ้างอิง: Inside HRT's Python Fork: Leveraging PEP 690 for Faster Imports