Wydajne wykonywanie operacji wejścia / wyjścia gniazda zostało rozwiązane za pomocą kqueue, epoll, portów zakończenia IO i podobnych. Wykonywanie asynchronicznych operacji wejścia / wyjścia pliku jest czymś w rodzaju późnego zjawiska (poza nakładającymi się operacjami wejścia / wyjścia systemu Windows i wczesnym wsparciem dla Posix AIO).
Jeśli szukasz wejścia / wyjścia gniazda, prawdopodobnie lepiej będzie, jeśli użyjesz jednego z powyższych mechanizmów.
Dlatego głównym celem AIO jest rozwiązanie problemu asynchronicznych operacji wejścia / wyjścia dysku. Najprawdopodobniej dlatego Mac OS X obsługuje AIO tylko dla zwykłych plików, a nie gniazd (ponieważ kqueue i tak robi to o wiele lepiej).
Operacje zapisu są zazwyczaj buforowane przez jądro i opróżniane w późniejszym czasie. Na przykład, gdy głowica odczytująca napędu przechodzi obok lokalizacji, w której ma zostać zapisany blok.
Jednak w przypadku operacji odczytu, jeśli chcesz, aby jądro ustalało priorytety i porządkowało odczyty, AIO jest naprawdę jedyną opcją. Oto dlaczego jądro może (teoretycznie) zrobić to lepiej niż jakakolwiek aplikacja na poziomie użytkownika:
- Jądro widzi wszystkie dyskowe operacje we / wy, a nie tylko zadania dyskowe aplikacji, i może je porządkować na poziomie globalnym
- Jądro (może) wiedzieć, gdzie jest głowica odczytu dysku i może wybrać zadania odczytu, które przekazujesz do niego w optymalnej kolejności, aby przesunąć głowicę na najmniejszą odległość
- Jądro może korzystać z natywnego kolejkowania poleceń celu dalszej optymalizacji operacji odczytu
- Możesz być w stanie wykonać więcej operacji odczytu na wywołanie systemowe używając lio_listio () niż z readv (), szczególnie jeśli twoje odczyty nie są (logicznie) ciągłe, oszczędzając odrobinę narzutu wywołań systemowych.
- Twój program może być nieco prostszy z AIO, ponieważ nie potrzebujesz dodatkowego wątku do blokowania w wywołaniu odczytu lub zapisu.
To powiedziawszy, posix AIO ma dość niezręczny interfejs, na przykład:
- Jedynym wydajnym i dobrze obsługiwanym sposobem wywołań zwrotnych zdarzeń są sygnały, co utrudnia użycie go w bibliotece, ponieważ oznacza użycie numerów sygnałów z globalnej przestrzeni nazw sygnałów. Jeśli Twój system operacyjny nie obsługuje sygnałów czasu rzeczywistego, oznacza to również, że musisz przejrzeć wszystkie oczekujące żądania, aby dowiedzieć się, które z nich zostało ukończone (dotyczy to na przykład systemu Mac OS X, a nie Linuksa). Przechwytywanie sygnałów w środowisku wielowątkowym również stwarza pewne trudne ograniczenia. Zwykle nie możesz zareagować na zdarzenie wewnątrz obsługi sygnału, ale musisz podnieść sygnał, napisać do potoku lub użyć signalfd () (w systemie Linux).
- lio_suspend () ma te same problemy co select (), nie skaluje się dobrze z liczbą zadań.
- lio_listio (), jak zaimplementowano, ma dość ograniczoną liczbę zadań, które można przekazać, i nie jest trywialne znalezienie tego ograniczenia w przenośny sposób. Musisz wywołać sysconf (_SC_AIO_LISTIO_MAX), co może się nie powieść, w takim przypadku możesz użyć definicji AIO_LISTIO_MAX, która niekoniecznie jest zdefiniowana, ale możesz użyć 2, które jest zdefiniowane jako gwarantowane do obsługi.
Jeśli chodzi o rzeczywistą aplikację korzystającą z posix AIO, możesz rzucić okiem na lighttpd (lighty), który również opublikował pomiar wydajności podczas wprowadzania wsparcia.
Większość platform posix obsługuje już posix AIO (Linux, BSD, Solaris, AIX, tru64). Windows obsługuje to poprzez nakładające się pliki I / O. Rozumiem, że tylko Solaris, Windows i Linux naprawdę obsługują async. plik I / O aż do sterownika, podczas gdy inne systemy operacyjne emulują asynchroniczne. I / O z wątkami jądra. Linux jest wyjątkiem, jego implementacja Posix AIO w glibc emuluje operacje asynchroniczne z wątkami na poziomie użytkownika, podczas gdy jego natywny asynchroniczny interfejs I / O (io_submit () itp.) Jest naprawdę asynchroniczny aż do sterownika, zakładając, że sterownik go obsługuje .
Uważam, że dość powszechne wśród systemów operacyjnych jest nieobsługiwanie POSIX AIO dla żadnego fd, ale ograniczenie tego do zwykłych plików.