การออกแบบ Async I/O ใหม่ของ Zig จุดประกายการถกเถียงเรื่องการอ้าง Function Coloring

ทีมชุมชน BigGo
การออกแบบ Async I/O ใหม่ของ Zig จุดประกายการถกเถียงเรื่องการอ้าง Function Coloring

ทีมพัฒนา Zig ได้เปิดตัวการออกแบบระบบ async I/O ใหม่ครั้งใหญ่ โดยอ้างว่าได้เอาชนะ function coloring ได้อย่างสมบูรณ์ - การอ้างที่ถกเถียงกันซึ่งได้จุดประกายการถกเถียงอย่างร้อนแรงในชุมชนโปรแกรมมิ่ง แนวทางใหม่นี้แนะนำอินเทอร์เฟซ Io แบบรวมเดียวที่มุ่งหวังจะแก้ปัญหาที่มีมายาวนานของ async function virality พร้อมทั้งรองรับโมเดลการทำงานหลายแบบ

ข้อถกเถียงเรื่อง Function Coloring

การอ้างอย่างกล้าหาญของทีม Zig ได้ดึงดูดการต่อต้านอย่างมากจากนักพัฒนาที่โต้แย้งว่าปัญหาพื้นฐานยังคงไม่ได้รับการแก้ไข นักวิจารณ์ชี้ให้เห็นว่าแม้ Zig จะได้กำจัดคีย์เวิร์ด async/await ที่ชัดเจนแล้ว แต่ฟังก์ชันตอนนี้ถูกแบ่งออกเป็นสองประเภท คือฟังก์ชันที่ต้องการพารามิเตอร์ Io และฟังก์ชันที่ไม่ต้องการ - ซึ่งโดยพื้นฐานแล้วคือการสร้าง function coloring รูปแบบใหม่

นักพัฒนาคนหนึ่งกล่าวว่ากฎทั้งห้าข้อจากบล็อกโพสต์ชื่อดัง What Color is Your Function? ยังคงใช้ได้กับระบบใหม่ของ Zig เป็นส่วนใหญ่ ฟังก์ชันที่ทำการ I/O operations ยังคงต้องถูกเรียกใช้แตกต่างกัน สามารถเรียกได้เฉพาะจากฟังก์ชันอื่นที่รองรับ I/O เท่านั้น และต้องการ context เพิ่มเติมเพื่อให้ทำงานได้อย่างถูกต้อง ความแตกต่างหลักคือ context นี้ตอนนี้ถูกส่งผ่านเป็นพารามิเตอร์ที่ชัดเจนแทนที่จะถูกฝังอยู่ใน syntax ของภาษา

อย่างไรก็ตาม ผู้สนับสนุนโต้แย้งว่าแนวทางนี้มีข้อได้เปรียบที่แท้จริงเหนือระบบ async แบบดั้งเดิม ไม่เหมือนกับภาษาที่ async functions ถูกล็อกเข้าไปในโมเดลการทำงานเฉพาะอย่างถาวร อินเทอร์เฟซ Io ของ Zig ช่วยให้โค้ดเดียวกันทำงานได้กับ blocking I/O, thread pools, green threads หรือ stackless coroutines ขึ้นอยู่กับการ implementation ที่เลือกใช้ตอน runtime

โมเดลการทำงานหลายแบบภายใต้อินเทอร์เฟซเดียว

การออกแบบใหม่รองรับการ implementation I/O ที่แตกต่างกันหลายแบบ แต่ละแบบมี trade-offs ที่แตกต่างกัน การ implementation แบบ blocking ที่ง่ายที่สุดจะ map โดยตรงไปยัง system calls แบบดั้งเดิมด้วย overhead ที่น้อยที่สุด การ implementation แบบ thread pool ใช้ blocking operations ข้ามหลาย OS threads เพื่อความเป็น parallelism Green threads ใช้ประโยชน์จาก system APIs เช่น io_uring บน Linux แม้ว่าแนวทางนี้จะต้องการความสามารถในการ stack swapping ที่จะไม่ทำงานบนแพลตฟอร์มเช่น WebAssembly

การ implementation ที่ทะเยอทะยานที่สุดเกี่ยวข้องกับ stackless coroutines ที่เปลี่ยน function bodies เป็น state machines แนวทางนี้สัญญาว่าจะเข้ากันได้กับ WebAssembly และสภาพแวดล้อมที่มีข้อจำกัดอื่นๆ แต่มันขึ้นอยู่กับการปรับแต่งของ compiler ที่ยังไม่ได้ถูก implement อย่างเต็มที่

ตัวเลือกการใช้งาน I/O ของ Zig :

  • Blocking I/O: การแมปโดยตรงไปยัง system calls โดยมี overhead น้อยที่สุด
  • Thread Pool: การดำเนินการแบบ blocking ที่ถูก multiplex ผ่าน OS threads
  • Green Threads: ใช้ io_uring ( Linux ) พร้อมกับ stack swapping ซึ่งไม่สามารถใช้งานร่วมกับ WebAssembly ได้
  • Stackless Coroutines: การแปลงเป็น state machine ที่สามารถใช้งานร่วมกับ WebAssembly ได้ (อยู่ในแผนการพัฒนา)

ข้อกังวลเรื่องประสิทธิภาพและการปรับแต่ง

การใช้ runtime polymorphism ผ่าน virtual function calls ได้ทำให้นักพัฒนาที่ใส่ใจประสิทธิภาพหวั่นไหว บางคนตั้งคำถามว่าภาษา systems ควรจะกำหนด overhead นี้กับการ I/O operations พื้นฐานหรือไม่ แม้ว่าค่าใช้จ่ายจะมักไม่มีนัยสำคัญเมื่อเทียบกับ I/O latency จริง

นักพัฒนา Zig ตอบโต้ว่าโมเดล single-compilation-unit ของพวกเขาช่วยให้มีการ devirtualization ที่รับประกันได้เมื่อมีการใช้การ implementation Io เพียงแบบเดียวตลอดทั้งโปรแกรม การปรับแต่งนี้ขจัด virtual call overhead ในสถานการณ์ปฏิบัติส่วนใหญ่ในขณะที่รักษาความยืดหยุ่นของการออกแบบอินเทอร์เฟซ

ชุมชนยังคงแบ่งแยกเรื่องว่า green threads แสดงถึงการถอยหลังหรือไม่ เนื่องจากภาษาอื่นเช่น Rust ได้เอาฟีเจอร์ที่คล้ายกันออกเนื่องจากข้อกังวลเรื่องประสิทธิภาพ การตัดสินใจของทีม Zig ที่จะรองรับหลายโมเดลพร้อมกันดูเหมือนจะเป็นการป้องกันความเสี่ยงต่อแนวทางใดแนวทางหนึ่งที่อาจพิสูจน์ว่าไม่เพียงพอ

ผลกระทบในทางปฏิบัติสำหรับนักพัฒนา

แม้จะมีการถกเถียงในเชิงทฤษฎี แต่นักพัฒนาหลายคนชื่นชมประโยชน์ในทางปฏิบัติของการนำโค้ดกลับมาใช้ใหม่ที่ระบบใหม่ช่วยให้เป็นไปได้ ไลบรารีที่เขียนขึ้นกับอินเทอร์เฟซ Io สามารถทำงานได้อย่างราบรื่นกับโมเดลการทำงานใดก็ได้ ขจัดความจำเป็นในการรักษาเวอร์ชัน sync และ async ที่แยกกันของฟังก์ชันการทำงานเดียวกัน

การส่งผ่านพารามิเตอร์ที่ชัดเจน แม้ว่าจะเพิ่ม syntactic overhead บ้าง แต่ให้การมองเห็นที่ชัดเจนว่าส่วนไหนของ codebase ที่ทำการ I/O operations ความโปร่งใสนี้สอดคล้องกับปรัชญาของ Zig ในการทำให้พฤติกรรมของระบบชัดเจนแทนที่จะซ่อนไว้หลัง language abstractions

ขณะที่ Zig ดำเนินต่อไปสู่การเผยแพร่ 1.0 การออกแบบใหม่นี้แสดงถึงการเดิมพันครั้งใหญ่กับแนวทางรวมเดียวต่อ I/O และ concurrency ว่ามันแก้ไข function coloring ได้จริงหรือเพียงแค่ห่อหุ้มปัญหาในรูปแบบที่น่าพอใจกว่านั้น ยังคงต้องรอดูเมื่อนักพัฒนาได้รับประสบการณ์ตรงกับระบบใหม่

อ้างอิง: Zig's New Async I/O