Состояние Linux async IO?

Я спрашиваю здесь, так как googling приводит вас к веселой поездке вокруг архивов без каких-либо намеков относительно того, что такое текущее состояние. Если вы поедете с Google, похоже, что в 2001-2003 годах асинхронный IO был в ярости, и к 2006 году появились такие вещи, как epoll и libaio; kevent появился, но, похоже, исчез, и, насколько я могу судить, до сих пор нет хорошего способа смешивания сигнализации на основе завершения и готовности, async sendfile - это возможно? - и все остальное в однопоточном цикле событий.

Так что скажи мне, что я неправ, и все это радует! - и, что важно, какие API использовать.

Как Linux сравнивается с FreeBSD и другими операционными системами в этом отношении?

Ответ 1

AIO как таковой все еще несколько ограничен, и реальная боль, с которой можно начать, но она работает по большей части, как только вы ее выкопали.

У него есть некоторые, на мой взгляд, серьезные ошибки, но это действительно функции. Например, при отправке определенного количества команд или данных ваш подающий поток будет блокироваться. Я не помню точного обоснования этой функции, но ответ, который я получил, тогда был чем-то вроде "да, конечно, у ядра есть ограничение на размер очереди, что и предназначено". Это приемлемо, если вы отправляете несколько тысяч запросов... очевидно, что где-то должен быть предел. Это может иметь смысл и с точки зрения DoS (в противном случае вредоносная программа может привести к тому, что ядро ​​исчерпает память, отправив миллиард запросов). Но тем не менее, это то, что вы можете реально встретить с "нормальными" числами (сто или около того), и это поразит вас неожиданно, что не хорошо. Кроме того, если вы отправляете только полдюжины запросов, и они немного больше (некоторые мегабайты данных), то это может произойти, по-видимому, потому, что ядро ​​разбивает их на подзапросы. Который, опять-таки, имеет смысл, но, видя, как документы не говорят вам, следует ожидать, что нет никакой разницы (кроме взятия дольше), читаете ли вы 500 байт или 50 мегабайт данных.

Кроме того, похоже, что нет никакого способа делать буферизованный AIO, по крайней мере, на любой из моих систем Debian и Ubuntu (хотя я видел, как другие люди жалуются на полную противоположность, то есть небуферизованные записи, фактически поступающие через буферы), Из того, что я могу видеть в своих системах, AIO действительно асинхронен с отключенной буферизацией, что является позором (именно поэтому я сейчас использую уродливую конструкцию вокруг сопоставления памяти и рабочий поток).

Важная проблема с чем-либо асинхронным - это возможность epoll_wait() на ней, что важно, если вы делаете что-либо еще, кроме дискового ввода-вывода (например, получения сетевого трафика). Конечно, есть io_getevents, но это не так желательно/полезно, поскольку оно работает только для одной особой вещи.

В последних ядрах существует поддержка eventfd. На первый взгляд это кажется бесполезным, поскольку неясно, как это может быть полезно в любом случае. Однако для вашего спасения есть недокументированная функция io_set_eventfd, которая позволяет связать AIO с eventfd, который является epoll_wait() - способным. Вам нужно копать в заголовках, чтобы узнать об этом, но это, безусловно, есть, и все работает отлично.

Ответ 2

Асинхронный диск IO жив и ногами... он фактически поддерживается и работает достаточно хорошо сейчас, но имеет значительные ограничения (но с достаточной функциональностью, которую некоторые из основных пользователей могут с пользой использовать, например, MySQL Innodb делает в последняя версия).

Асинхронный диск IO - это способность вызывать операции ввода-вывода диска неблокируемым образом (в одном потоке) и ждать их завершения. Это прекрасно работает, http://lse.sourceforge.net/io/aio.html содержит больше информации.

AIO достаточно для типичного приложения (сервера базы данных), чтобы иметь возможность использовать его. AIO - хорошая альтернатива либо созданию большого количества потоков, выполняющих синхронный ввод-вывод, либо использование разброса/сбора в семействе системных вызовов preobe, которые теперь существуют.

Можно выполнить синхронное задание ввода-вывода "список покупок", используя новый вызов preadv, куда будет идти ядро, и получить кучу страниц из разных смещений в файле. Это нормально, пока у вас есть только один файл для чтения. (NB: существует эквивалентная функция записи).

poll, epoll и т.д. - это просто причудливые способы сделать select(), которые страдают от меньшего количества ограничений и проблем с масштабируемостью - они, возможно, не могут быть легко смешаны с диском aio, но в реальном приложении вы, вероятно, можете обходите это довольно тривиально, используя потоки (некоторые серверы баз данных, как правило, выполняют эти операции в отдельных потоках). Опрос() хорош, epoll лучше, для большого количества файловых дескрипторов. select() также подходит для небольших количеств дескрипторов файлов (или, в частности, младших номеров дескрипторов файлов).

Ответ 3

Большинство из того, что я узнал об асинхронном вводе-выводе в Linux, работало над источником Lighttpd. Это однопоточный веб-сервер, который обрабатывает множество одновременных подключений, используя то, что, по его мнению, является лучшим из всех доступных асинхронных механизмов ввода-вывода в запущенной системе. Взгляните на источник, он поддерживает Linux, BSD и (я думаю) несколько других операционных систем.