Bagaimana status POSIX asynchronous I / O (AIO)?

93

Ada halaman yang tersebar di seluruh web yang menjelaskan fasilitas POSIX AIO dalam jumlah detail yang bervariasi. Tak satu pun dari mereka yang sangat baru. Tidak jelas apa yang sebenarnya mereka gambarkan. Misalnya, situs web "resmi" (?) Untuk dukungan I / O asinkron kernel Linux di sini mengatakan bahwa soket tidak berfungsi, tetapi halaman manual "aio.h" di workstation Ubuntu 8.04.1 saya semuanya tampaknya menyiratkan bahwa itu bekerja untuk deskriptor file sewenang-wenang. Lalu ada proyek lain yang tampaknya bekerja di lapisan perpustakaan dengan lebih sedikit dokumentasi.

Saya ingin tahu:

  • Apa tujuan POSIX AIO? Mengingat bahwa contoh implementasi yang paling jelas yang dapat saya temukan mengatakan itu tidak mendukung soket, semuanya tampak aneh bagi saya. Apakah ini hanya untuk I / O disk asinkron? Jika demikian, mengapa API hiper-umum? Jika tidak, mengapa disk I / O menjadi hal pertama yang diserang?
  • Dimana ada contoh program POSIX AIO lengkap yang bisa saya lihat?
  • Apakah ada yang benar-benar menggunakannya?
  • Platform apa yang mendukung POSIX AIO? Bagian apa yang mereka dukung? Apakah ada yang benar-benar mendukung tersirat "Any I / O to any FD" yang <aio.h>tampaknya menjanjikan?

Mekanisme multiplexing lain yang tersedia untuk saya sangat bagus, tetapi pecahan informasi acak yang beredar di luar sana membuat saya penasaran.

Mesin terbang
sumber

Jawaban:

27

Jaringan I / O bukan prioritas untuk AIO karena semua orang yang menulis server jaringan POSIX menggunakan pendekatan non-pemblokiran berbasis peristiwa. Pendekatan Java gaya lama "miliaran benang pemblokiran" sangat menyebalkan.

I / O penulisan disk sudah di-buffer dan I / O baca disk dapat diambil lebih dulu ke dalam buffer menggunakan fungsi seperti posix_fadvise. Hal ini membuat I / O disk langsung yang tidak buffer sebagai satu-satunya tujuan yang berguna untuk AIO.

I / O langsung tanpa buffer hanya benar-benar berguna untuk database transaksional, dan mereka cenderung menulis utas atau proses mereka sendiri untuk mengelola I / O disk mereka.

Jadi, pada akhir yang meninggalkan POSIX AIO dalam posisi tidak melayani setiap tujuan yang bermanfaat. Jangan gunakan itu.

Zan Lynx
sumber
8
Bagaimana dengan membaca / menulis dari sistem berkas jaringan (NFS, Samba)?
Alex B
1
baik. Saya memiliki beberapa penulis besar dan bodoh yang, jika saya membiarkan mereka masuk ke cache, akan mencapai rasio dirty_ratio pada puncaknya, memblokir orang lain. Jika saya hanya menggunakan IO langsung pada mereka, itu terlalu lambat. Jika saya hanya memiliki 1 utas, saya dapat mengelola sendiri, tetapi akan sulit untuk mendukung prioritas IO yang berbeda dalam 1 alur. AIO + CFQ benar-benar terlihat kombinasi yang bagus, jika AIO bekerja
n-alexander
37
Saya tidak setuju. Disk I / O cenderung memiliki buffer tetapi dapat diblokir. Ketika melakukan polling () pada file FD, FD selalu melaporkan bahwa FD dapat dibaca, bahkan ketika akan diblokir. Ini membuat tidak mungkin untuk melakukan operasi non-pemblokiran pada file disk secara evented, kecuali seseorang menggunakan utas atau AIO.
Hongli
2
@Matt: Urutan tidak penting untuk soket datagram. @Zan: async I / O sangat bagus untuk prebuffering real-time streaming data, misalnya media player.
Ben Voigt
13
Tidak benar bahwa AIO tidak berguna dalam sistem berbasis peristiwa. Anda benar-benar bisa mendapatkan jaringan tanpa salinan dengan AIO yang tepat, yang tidak bisa Anda lakukan dengan notifikasi berbasis acara ke recv (). Hal-hal lain mungkin bersekongkol untuk menjadikan ini sebagian besar sebagai batasan teoretis, tetapi saya pikir kurangnya AIO yang tepat (a la OVERLAPPED di Windows) adalah salah satu lubang besar terakhir di Linux.
Jon Watte
70

Melakukan soket I / O secara efisien telah diselesaikan dengan kqueue, epoll, port penyelesaian IO dan sejenisnya. Melakukan asynchronous file I / O adalah semacam pendatang yang terlambat (selain dari Windows 'overlapped I / O dan solaris early support untuk posix AIO).

Jika Anda ingin melakukan soket I / O, Anda mungkin lebih baik menggunakan salah satu mekanisme di atas.

Oleh karena itu, tujuan utama AIO adalah untuk memecahkan masalah I / O disk asinkron. Ini kemungkinan besar mengapa Mac OS X hanya mendukung AIO untuk file biasa, dan bukan soket (karena kqueue melakukannya dengan jauh lebih baik).

Operasi tulis biasanya di-cache oleh kernel dan dihapus di lain waktu. Misalnya ketika kepala baca drive kebetulan melewati lokasi di mana blok itu akan ditulis.

Namun, untuk operasi baca, jika Anda ingin kernel memprioritaskan dan memesan bacaan Anda, AIO benar-benar satu-satunya pilihan. Inilah mengapa kernal dapat (secara teoritis) melakukannya lebih baik daripada aplikasi level pengguna mana pun:

  • Kernel melihat semua disk I / O, bukan hanya pekerjaan disk aplikasi Anda, dan dapat memesannya di tingkat global
  • Kernel (mungkin) tahu di mana kepala pembacaan disk berada, dan dapat memilih tugas baca yang Anda sampaikan kepadanya dalam urutan yang optimal, untuk memindahkan kepala ke jarak terpendek
  • Kernel dapat memanfaatkan antrian perintah asli untuk lebih mengoptimalkan operasi baca Anda
  • Anda mungkin dapat mengeluarkan lebih banyak operasi baca per panggilan sistem menggunakan lio_listio () daripada dengan readv (), terutama jika pembacaan Anda tidak (secara logis) berdekatan, menghemat sedikit overhead system call.
  • Program Anda mungkin sedikit lebih sederhana dengan AIO karena Anda tidak memerlukan utas tambahan untuk memblokir panggilan baca atau tulis.

Bisa dikatakan, posix AIO memiliki antarmuka yang cukup canggung, misalnya:

  • Satu-satunya cara callback peristiwa yang efisien dan didukung dengan baik adalah melalui sinyal, yang membuatnya sulit digunakan di perpustakaan, karena ini berarti menggunakan nomor sinyal dari ruang nama sinyal global proses. Jika OS Anda tidak mendukung sinyal realtime, itu juga berarti Anda harus mengulang semua permintaan yang belum selesai untuk mencari tahu mana yang benar-benar selesai (ini adalah kasus untuk Mac OS X misalnya, bukan Linux). Menangkap sinyal dalam lingkungan multi-thread juga membuat beberapa pembatasan rumit. Anda biasanya tidak dapat bereaksi terhadap kejadian di dalam penangan sinyal, tetapi Anda harus menaikkan sinyal, menulis ke pipa atau menggunakan signalfd () (di linux).
  • lio_suspend () memiliki masalah yang sama seperti select (), tidak diskalakan dengan baik dengan jumlah pekerjaan.
  • lio_listio (), seperti yang diterapkan memiliki jumlah pekerjaan yang cukup terbatas yang dapat Anda lewati, dan tidak mudah menemukan batas ini dengan cara portabel. Anda harus memanggil sysconf (_SC_AIO_LISTIO_MAX), yang mungkin gagal, dalam hal ini Anda dapat menggunakan definisi AIO_LISTIO_MAX, yang belum tentu ditentukan, tetapi kemudian Anda dapat menggunakan 2, yang didefinisikan sebagai dijamin akan didukung.

Sedangkan untuk aplikasi dunia nyata menggunakan posix AIO, Anda dapat melihat lighttpd (lighty), yang juga memposting pengukuran kinerja saat memperkenalkan dukungan.

Kebanyakan platform posix mendukung posix AIO sekarang (Linux, BSD, Solaris, AIX, tru64). Windows mendukungnya melalui file I / O yang tumpang tindih. Pemahaman saya adalah bahwa hanya Solaris, Windows dan Linux yang benar-benar mendukung async. file I / O sampai ke driver, sedangkan OS lain meniru async. I / O dengan utas kernel. Linux menjadi pengecualian, implementasi posix AIO-nya di glibc mengemulasi operasi asinkron dengan utas tingkat pengguna, sedangkan antarmuka I / O asinkron aslinya (io_submit () dll.) Benar-benar asinkron sampai ke driver, dengan asumsi driver mendukungnya .

Saya percaya itu cukup umum di antara OS untuk tidak mendukung posix AIO untuk fd apa pun, tetapi membatasinya ke file biasa.

Arvid
sumber
Windows memiliki file disk pendukung I / O OVERLAPPED sejak Win32 pertama kali keluar. Ini sama sekali tidak baru. Dan pada POSIX, namespace sinyal bukanlah proses global, melainkan per utas. Sinyal dikirim ke utas tertentu (atau apakah aio pengecualian untuk itu, tidak ingat pasti?).
Ben Voigt
1
Tidak ada cara untuk menentukan utas mana yang mengirimkan sinyalnya AIO. Di linux tampaknya sebagian besar mengirimkannya ke utas yang mengeluarkan perintah aio _ * (), tetapi tidak selalu (satu-satunya solusi yang saya temukan untuk ini adalah membuat beberapa signalfds). Ada patch linux di milis kernel beberapa tahun yang lalu yang akan menambahkan ini, tetapi tidak pernah berhasil, dan itu akan menjadi ekstensi untuk POSIX. Di Mac OS X, sinyal tampaknya sebagian besar dikirim ke utas utama (menurut pengalaman saya). Saya tidak berpikir POSIX memerlukan perilaku tertentu, jika demikian, saya akan senang melihat bagian dari spesifikasi.
Arvid
5
Implementasi glibc dari aio_read / write menggunakan utas di userland, jadi bahkan utas kernel tidak digunakan di sini.
Marenz
Apa artinya "selalu biasanya"? Tulisan di-cache oleh kernel untuk metode apa pun, atau saat menggunakan AIO? Sepertinya harus ada cara untuk memiliki perangkat lunak memastikan penulisan berhasil diselesaikan; jika tidak, integritas dan tujuan transaksional tidak dapat dipenuhi.
MikeB
Contoh langsung lainnya di mana Anda dapat menggunakan AIO adalah nginx. Semua mode didukung. Jika Anda lebih suka memindahkan ke utas userland, biasanya Anda akan merasa jauh lebih buruk daripada IO langsung, tetapi AIO asli Linux setara dengan IO langsung. Situasi ketika AIO dapat sangat bermanfaat adalah tekanan cache halaman yang parah. Perbedaan konseptual antara Async dan IO Langsung dapat dilihat di sini ftp.dei.uc.pt/pub/linux/kernel/people/suparna/aio-linux.pdf
sumbu
2

Ada aio_write - diimplementasikan di glibc; panggilan pertama dari fungsi aio_read atau aio_write memunculkan sejumlah utas mode pengguna, aio_write atau aio_read permintaan posting ke utas itu, utas melakukan pread / pwrite dan ketika selesai jawabannya dikirim kembali ke utas panggilan yang diblokir.

Ada juga aio 'nyata' - didukung oleh level kernel (perlu libaio untuk itu, lihat panggilan io_submit http://linux.die.net/man/2/io_submit ); juga membutuhkan O_DIRECT untuk itu (juga mungkin tidak didukung oleh semua sistem file, tetapi yang utama mendukungnya)

Lihat disini:

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

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

Perbedaan antara POSIX AIO dan libaio di Linux?

MichaelMoser
sumber
Banyak kekurangan aio_writeyang tercakup di atas, di stackoverflow.com/a/5307557/13564
Glyph