สถานะของ POSIX asynchronous I / O (AIO) คืออะไร?


93

มีเพจที่กระจายอยู่ทั่วเว็บที่อธิบายสิ่งอำนวยความสะดวก POSIX AIO ในรายละเอียดที่แตกต่างกัน ไม่มีสิ่งใดที่น่ากลัวล่าสุด ยังไม่ชัดเจนว่าพวกเขากำลังอธิบายอะไรกันแน่ ตัวอย่างเช่นเว็บไซต์ "อย่างเป็นทางการ" (?) สำหรับการสนับสนุน I / O แบบอะซิงโครนัสเคอร์เนลของ Linux ที่นี่บอกว่าซ็อกเก็ตไม่ทำงาน แต่หน้าคู่มือ "aio.h" บนเวิร์กสเตชัน Ubuntu 8.04.1 ของฉันทั้งหมดดูเหมือนจะบ่งบอกเป็นนัยว่า มันใช้งานได้กับตัวอธิบายไฟล์โดยพลการ จากนั้นมีโครงการอื่นที่ดูเหมือนว่าจะทำงานที่เลเยอร์ไลบรารีที่มีเอกสารประกอบน้อยกว่า

ฉันต้องการทราบ:

  • POSIX AIO มีจุดประสงค์อะไร? เนื่องจากตัวอย่างที่ชัดเจนที่สุดของการใช้งานที่ฉันพบบอกว่ามันไม่รองรับซ็อกเก็ตดูเหมือนว่าฉันจะแปลก ๆ เป็นเพียงสำหรับ async disk I / O หรือไม่ ถ้าเป็นเช่นนั้นเหตุใดจึงต้องใช้ API แบบไฮเปอร์ทั่วไป ถ้าไม่ทำไมดิสก์ I / O จึงเป็นสิ่งแรกที่ถูกโจมตี
  • มีตัวอย่างโปรแกรม POSIX AIO ที่สมบูรณ์ที่ฉันสามารถดูได้ที่ไหน
  • ไม่มีใครใช้จริงจริงหรือ?
  • แพลตฟอร์มใดบ้างที่รองรับ POSIX AIO พวกเขาสนับสนุนส่วนใดบ้าง ไม่มีใครสนับสนุน "I / O ใด ๆ กับ FD ใด ๆ " ที่<aio.h>ดูเหมือนจะสัญญา

กลไกมัลติเพล็กซ์อื่น ๆ ที่มีให้ฉันเป็นสิ่งที่ดีอย่างสมบูรณ์แบบ แต่ข้อมูลแบบสุ่มที่ลอยอยู่รอบ ๆ ทำให้ฉันอยากรู้อยากเห็น

คำตอบ:


27

Network I / O ไม่ใช่ลำดับความสำคัญสำหรับ AIO เนื่องจากทุกคนที่เขียนเซิร์ฟเวอร์เครือข่าย POSIX ใช้วิธีการที่อิงตามเหตุการณ์และไม่ปิดกั้น วิธีการ "บล็อกเธรดพันล้านเธรด" แบบเก่าของ Java นั้นได้รับผลกระทบอย่างมาก

I / O การเขียนดิสก์ถูกบัฟเฟอร์แล้วและดิสก์ที่อ่าน I / O สามารถกำหนดไว้ล่วงหน้าในบัฟเฟอร์โดยใช้ฟังก์ชันเช่น posix_fadvise ซึ่งทำให้ I / O ดิสก์โดยตรงที่ไม่มีบัฟเฟอร์เป็นจุดประสงค์เดียวที่มีประโยชน์สำหรับ AIO

I / O โดยตรงที่ไม่มีบัฟเฟอร์มีประโยชน์มากสำหรับฐานข้อมูลแบบทรานแซคชันเท่านั้นและผู้ที่มักจะเขียนเธรดหรือกระบวนการของตนเองเพื่อจัดการดิสก์ I / O ของตน

ดังนั้นในตอนท้ายที่ทำให้ POSIX AIO อยู่ในตำแหน่งที่ไม่ตอบสนองวัตถุประสงค์ที่เป็นประโยชน์ใด ๆ อย่าใช้มัน.


8
แล้วการอ่าน / เขียนจากระบบไฟล์เครือข่าย (NFS, Samba) ล่ะ?
Alex B

1
ดี. ฉันมีนักเขียนใบ้รายใหญ่หลายคนซึ่งถ้าฉันปล่อยให้พวกเขาไปที่แคชมันจะโดน dirty_ratio ที่จุดสูงสุดบล็อกคนอื่น ๆ ถ้าฉันแค่ใช้ IO โดยตรงกับมันก็ช้าเกินไป ถ้าฉันมีเพียง 1 เธรดฉันสามารถจัดการได้ด้วยตัวเอง แต่มันยากที่จะรองรับลำดับความสำคัญ IO ที่แตกต่างกันใน 1 ดอกยาง AIO + CFQ wouls ดูเหมือนเป็นการผสมผสานที่ดีจริงๆถ้า AIO ทำงานได้
n-alexander

37
ฉันไม่เห็นด้วย. ดิสก์ I / O มีแนวโน้มที่จะถูกบัฟเฟอร์ แต่สามารถบล็อกได้ เมื่อสำรวจความคิดเห็น () ในไฟล์ FD จะรายงานเสมอว่า FD สามารถอ่านได้แม้ว่าจะบล็อกก็ตาม สิ่งนี้ทำให้ไม่สามารถดำเนินการแบบไม่ปิดกั้นบนไฟล์ดิสก์ในลักษณะที่เป็นเหตุการณ์เว้นแต่จะมีการใช้เธรดหรือ AIO
Hongli

2
@Matt: คำสั่งซื้อไม่สำคัญสำหรับซ็อกเก็ตดาตาแกรม @Zan: async I / O นั้นดีมากสำหรับการ prebuffering ข้อมูลสตรีมแบบเรียลไทม์เช่นเครื่องเล่นสื่อ
Ben Voigt

13
ไม่เป็นความจริงที่ AIO จะไร้ประโยชน์ในระบบตามเหตุการณ์ คุณสามารถเข้าสู่ระบบเครือข่ายแบบศูนย์ด้วย AIO ที่เหมาะสมซึ่งคุณไม่สามารถทำได้ด้วยการแจ้งเตือนตามเหตุการณ์เพื่อ recv () สิ่งอื่น ๆ อาจรวมกันเพื่อให้สิ่งนี้เป็นข้อ จำกัด ทางทฤษฎีเป็นส่วนใหญ่ แต่ฉันคิดว่าการขาด AIO ที่เหมาะสม (a la OVERLAPPED บน Windows) เป็นหนึ่งในช่องโหว่สุดท้ายใน Linux
Jon Watte

70

การทำซ็อกเก็ต 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 ใด ๆ แต่ จำกัด ไว้ที่ไฟล์ปกติ


Windows มี OVERLAPPED I / O ที่รองรับไฟล์ดิสก์ตั้งแต่ Win32 ออกมาครั้งแรก ไม่ใช่เรื่องใหม่เลย และใน POSIX เนมสเปซของสัญญาณไม่ได้เป็นกระบวนการส่วนกลาง แต่เป็นแบบต่อเธรด สัญญาณถูกส่งไปยังเธรดเฉพาะ (หรือเป็นข้อยกเว้นของ aio จำไม่ได้แน่นอน?)
Ben Voigt

1
ไม่มีวิธีระบุว่า AIO เธรดใดส่งสัญญาณไปยัง บน linux ดูเหมือนว่าส่วนใหญ่จะส่งไปยังเธรดที่ออกคำสั่ง aio _ * () แต่ไม่เสมอไป (ทางออกเดียวที่ฉันพบคือการสร้าง signalfds หลายตัว) มีการแพตช์ linux ในรายการส่งเมลของเคอร์เนลเมื่อไม่กี่ปีที่ผ่านมาซึ่งจะเพิ่มสิ่งนี้ แต่ไม่เคยมีมาก่อนและมันน่าจะเป็นส่วนขยายของ POSIX ใน Mac OS X สัญญาณส่วนใหญ่จะส่งไปยังเธรดหลัก (จากประสบการณ์ของฉัน) ฉันไม่คิดว่า POSIX ต้องการพฤติกรรมที่เฉพาะเจาะจงถ้าเป็นเช่นนั้นฉันชอบที่จะเห็นส่วนหนึ่งของข้อมูลจำเพาะ
Arvid

5
การใช้ aio_read / write ของ glibc ใช้เธรดในยูสเซอร์แลนด์ดังนั้นจึงไม่ได้ใช้เคอร์เนลเธรดที่นี่
Marenz

"โดยทั่วไปเสมอ" หมายความว่าอย่างไร การเขียนถูกแคชโดยเคอร์เนลสำหรับเมธอดใด ๆ หรือเมื่อใช้ AIO? ดูเหมือนว่าจะต้องมีวิธีการที่จะทำให้ซอฟต์แวร์แน่ใจว่าการเขียนเสร็จสมบูรณ์ มิฉะนั้นจะไม่สามารถบรรลุเป้าหมายด้านความซื่อสัตย์และธุรกรรมได้
MikeB

อีกตัวอย่างสดที่คุณสามารถใช้ AIO คือ nginx รองรับทุกโหมด หากคุณต้องการถ่ายโอนไปยังเธรดของผู้ใช้โดยปกติคุณจะพบว่ามันแย่กว่า IO โดยตรงมาก แต่ AIO เนทีฟของ Linux นั้นเทียบเท่ากับ IO โดยตรง สถานการณ์ที่ AIO สามารถให้ประโยชน์อย่างมากคือแรงกดแคชของเพจ ความแตกต่างของแนวคิดระหว่าง Async และ Direct IOs สามารถดูได้ที่นี่ftp.dei.uc.pt/pub/linux/kernel/people/suparna/aio-linux.pdf
วิ


2

มี aio_write - ใช้งานใน glibc; การเรียกครั้งแรกของฟังก์ชัน aio_read หรือ aio_write จะสร้างเธรดโหมดผู้ใช้จำนวนมาก aio_write หรือ aio_read โพสต์ร้องขอไปยังเธรดนั้นเธรดจะทำ pread / pwrite และเมื่อเสร็จสิ้นคำตอบจะถูกโพสต์กลับไปยังเธรดการโทรที่ถูกบล็อก

Ther ยังเป็น aio 'จริง' - รองรับโดยระดับเคอร์เนล (ต้องการ libaio สำหรับสิ่งนั้นโปรดดูที่การโทร io_submit http://linux.die.net/man/2/io_submit ) ยังต้องการ O_DIRECT สำหรับสิ่งนั้น (อาจไม่ได้รับการสนับสนุนจากระบบไฟล์ทั้งหมด แต่ระบบหลัก ๆ รองรับ)

ดูที่นี่:

http://lse.sourceforge.net/io/aio.html

http://linux.die.net/man/2/io_submit

ความแตกต่างระหว่าง POSIX AIO และ libaio บน Linux


ข้อบกพร่องหลายประการaio_writeได้กล่าวถึงข้างต้นในstackoverflow.com/a/5307557/13564
Glyph
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.