การทำซ็อกเก็ต I / O อย่างมีประสิทธิภาพได้รับการแก้ไขด้วย kqueue, epoll, พอร์ตเสร็จสิ้น IO และสิ่งที่ชอบ การทำไฟล์ I / O แบบอะซิงโครนัสเป็นประเภทของผู้มาช้า (นอกเหนือจาก I / O ที่ซ้อนทับกันของ windows และการสนับสนุน Solaris ในช่วงต้นสำหรับ posix AIO)
หากคุณกำลังมองหาการทำซ็อกเก็ต I / O คุณน่าจะดีกว่าที่จะใช้หนึ่งในกลไกข้างต้น
ดังนั้นจุดประสงค์หลักของ AIO คือเพื่อแก้ปัญหาของ I / O ดิสก์แบบอะซิงโครนัส นี่เป็นสาเหตุที่ Mac OS X รองรับเฉพาะ AIO สำหรับไฟล์ปกติเท่านั้นและไม่ใช่ซ็อกเก็ต (เนื่องจาก kqueue ทำได้ดีกว่ามาก)
โดยทั่วไปการดำเนินการเขียนจะถูกแคชโดยเคอร์เนลและล้างออกในเวลาต่อมา ตัวอย่างเช่นเมื่อหัวอ่านของไดรฟ์เคลื่อนผ่านตำแหน่งที่จะเขียนบล็อก
อย่างไรก็ตามสำหรับการดำเนินการอ่านหากคุณต้องการให้เคอร์เนลจัดลำดับความสำคัญและเรียงลำดับการอ่านของคุณ AIO เป็นตัวเลือกเดียวจริงๆ นี่คือสาเหตุที่เคอร์เนลสามารถทำได้ (ในทางทฤษฎี) ดีกว่าแอปพลิเคชันระดับผู้ใช้ใด ๆ :
- เคอร์เนลมองเห็น I / O ของดิสก์ทั้งหมดไม่ใช่เฉพาะงานดิสก์ของแอปพลิเคชันของคุณและสามารถสั่งซื้อได้ในระดับโลก
- เคอร์เนล (อาจ) รู้ว่าหัวอ่านของดิสก์อยู่ที่ใดและสามารถเลือกงานอ่านที่คุณส่งต่อไปได้ตามลำดับที่เหมาะสมเพื่อย้ายส่วนหัวในระยะทางที่สั้นที่สุด
- เคอร์เนลสามารถใช้ประโยชน์จากการจัดคิวคำสั่งเนทีฟเพื่อเพิ่มประสิทธิภาพการดำเนินการอ่านของคุณเพิ่มเติม
- คุณอาจสามารถออกการดำเนินการอ่านต่อการเรียกระบบโดยใช้ lio_listio () ได้มากกว่าด้วย readv () โดยเฉพาะอย่างยิ่งหากการอ่านของคุณไม่ (มีเหตุผล) ติดกันซึ่งจะช่วยประหยัดค่าใช้จ่ายในการโทรระบบเล็กน้อย
- โปรแกรมของคุณอาจจะง่ายกว่าเล็กน้อยด้วย AIO เนื่องจากคุณไม่จำเป็นต้องมีเธรดเพิ่มเติมเพื่อบล็อกในการโทรอ่านหรือเขียน
ที่กล่าวว่า posix AIO มีอินเทอร์เฟซที่ค่อนข้างน่าอึดอัดเช่น:
- ค่าเฉลี่ยของการเรียกกลับเหตุการณ์ที่มีประสิทธิภาพและได้รับการสนับสนุนอย่างดีเพียงอย่างเดียวคือผ่านสัญญาณซึ่งทำให้ใช้งานในไลบรารีได้ยากเนื่องจากหมายถึงการใช้หมายเลขสัญญาณจากเนมสเปซสัญญาณระดับกระบวนการ หากระบบปฏิบัติการของคุณไม่รองรับสัญญาณเรียลไทม์ก็หมายความว่าคุณต้องวนซ้ำคำขอที่ค้างอยู่ทั้งหมดของคุณเพื่อดูว่าคำขอใดเสร็จสิ้นจริง (กรณีเช่นนี้สำหรับ Mac OS X ไม่ใช่ Linux) การจับสัญญาณในสภาพแวดล้อมแบบมัลติเธรดยังทำให้มีข้อ จำกัด ที่ยุ่งยาก โดยทั่วไปคุณไม่สามารถตอบสนองต่อเหตุการณ์ภายในตัวจัดการสัญญาณได้ แต่คุณต้องเพิ่มสัญญาณเขียนไปยังไพพ์หรือใช้ signalfd () (บน linux)
- lio_suspend () มีปัญหาเช่นเดียวกับที่ select () ทำมันไม่ได้ปรับขนาดได้ดีกับจำนวนงาน
- lio_listio () เนื่องจากการใช้งานมีจำนวนงานที่ค่อนข้าง จำกัด ที่คุณสามารถส่งผ่านได้และการหาข้อ จำกัด นี้ในแบบพกพาก็ไม่ใช่เรื่องเล็กน้อย คุณต้องเรียก sysconf (_SC_AIO_LISTIO_MAX) ซึ่งอาจล้มเหลวในกรณีนี้คุณสามารถใช้การกำหนด AIO_LISTIO_MAX ซึ่งไม่จำเป็นต้องกำหนดไว้ แต่จากนั้นคุณสามารถใช้ 2 ซึ่งถูกกำหนดโดยรับประกันว่าจะได้รับการสนับสนุน
สำหรับการใช้งานจริงโดยใช้ posix AIO คุณสามารถดู lighttpd (lighty) ซึ่งโพสต์การวัดประสิทธิภาพเมื่อแนะนำการสนับสนุน
แพลตฟอร์ม posix ส่วนใหญ่รองรับ posix AIO ในตอนนี้ (Linux, BSD, Solaris, AIX, tru64) Windows รองรับผ่านไฟล์ I / O ที่ทับซ้อนกัน ความเข้าใจของฉันคือ Solaris, Windows และ Linux เท่านั้นที่สนับสนุน async อย่างแท้จริง ไฟล์ I / O ลงไปที่ไดรเวอร์ทั้งหมดในขณะที่ระบบปฏิบัติการอื่น ๆ จะเลียนแบบ async I / O พร้อมเคอร์เนลเธรด Linux เป็นข้อยกเว้นการนำ posix AIO ไปใช้ใน glibc จะจำลองการดำเนินการ async กับเธรดระดับผู้ใช้ในขณะที่อินเทอร์เฟซ async I / O ดั้งเดิม (io_submit () เป็นต้น) เป็นแบบอะซิงโครนัสอย่างแท้จริงจนถึงไดรเวอร์โดยสมมติว่าไดรเวอร์รองรับ .
ฉันเชื่อว่าเป็นเรื่องธรรมดาใน OSes ที่ไม่รองรับ posix AIO สำหรับ fd ใด ๆ แต่ จำกัด ไว้ที่ไฟล์ปกติ