ti-enxame.com

Qual é o status da E / S assíncrona POSIX (AIO)?

Existem páginas espalhadas pela web que descrevem os recursos do POSIX AIO em diferentes quantidades de detalhes. Nenhum deles é terrivelmente recente. Não está claro o que exatamente eles estão descrevendo. Por exemplo, o "official" (?) site de suporte a E/S assíncrono do kernel Linux aqui diz que os soquetes não funcionam, mas as páginas de manual "aio.h" no meu Ubuntu 8.04. 1 estação de trabalho parece implicar que funciona para descritores de arquivos arbitrários. Depois, há outro projeto que parece funcionar na camada da biblioteca com ainda menos documentação.

Eu gostaria de saber:

  • Qual é o objetivo do POSIX AIO? Dado que o exemplo mais óbvio de uma implementação que posso encontrar diz que não suporta soquetes, tudo parece estranho para mim. É apenas para E/S de disco assíncrono? Se sim, por que a API hiper-geral? Caso contrário, por que a E/S de disco é a primeira coisa que foi atacada?
  • Onde há exemplos completos de programas POSIX AIO que eu posso olhar?
  • Alguém realmente usa isso de verdade?
  • Quais plataformas suportam o POSIX AIO? Que partes dele eles suportam? Alguém realmente suporta o implícito "Qualquer E/S para qualquer FD" que <aio.h> parece prometer?

Os outros mecanismos de multiplexação disponíveis são perfeitamente bons, mas os fragmentos aleatórios de informações que circulam por aí me deixaram curiosa.

93
Glyph

A E/S de rede não é uma prioridade para a AIO, porque todos que escrevem servidores de rede POSIX usam uma abordagem baseada em eventos e sem bloqueio. A abordagem antiga Java "bilhões de threads de bloqueio") é horrível.

A E/S de gravação em disco já está no buffer e a E/S de leitura no disco pode ser pré-buscada no buffer usando funções como posix_fadvise. Isso deixa a E/S direta e sem buffer de disco como o único objetivo útil para a AIO.

A E/S direta e sem buffer é realmente útil apenas para bancos de dados transacionais, e eles tendem a gravar seus próprios threads ou processos para gerenciar a E/S do disco.

Portanto, no final, isso deixa o POSIX AIO na posição de não servir qualquer propósito útil. Não use.

25
Zan Lynx

A execução de E/S de soquete com eficiência foi resolvida com kqueue, epoll, IO portas de conclusão e afins.) A execução de E/S de arquivo assíncrona é uma espécie de atraso (além da E/S sobreposta das janelas) O e solaris suporte inicial para posix AIO).

Se você está procurando fazer soquetes de E/S, provavelmente é melhor usar um dos mecanismos acima.

O principal objetivo do AIO é, portanto, resolver o problema de E/S de disco assíncrono. É mais provável que o Mac OS X suporte apenas o AIO para arquivos regulares e não soquetes (já que o kqueue faz isso muito melhor de qualquer maneira).

As operações de gravação geralmente são armazenadas em cache pelo kernel e liberadas posteriormente. Por exemplo, quando a cabeça de leitura da unidade passa pelo local em que o bloco deve ser gravado.

No entanto, para operações de leitura, se você deseja que o kernel priorize e ordene suas leituras, o AIO é realmente a única opção. Eis por que o kernal pode (teoricamente) fazer isso melhor do que qualquer aplicativo no nível do usuário:

  • O kernel vê todas as E/S de disco, não apenas as tarefas de disco de seus aplicativos, e pode solicitá-las em nível global
  • O kernel (maio) sabe onde está a cabeça de leitura do disco e pode escolher os trabalhos de leitura que você passa para ela na ordem ideal, para mover a cabeça a menor distância
  • O kernel pode tirar vantagem de enfileiramento de comandos nativo para otimizar ainda mais suas operações de leitura
  • Você poderá emitir mais operações de leitura por chamada do sistema usando lio_listio () do que com readv (), especialmente se suas leituras não forem (logicamente) contíguas, economizando um pouquinho da sobrecarga de chamadas do sistema.
  • Seu programa pode ser um pouco mais simples com o AIO, pois você não precisa de um encadeamento extra para bloquear uma chamada de leitura ou gravação.

Dito isto, o posix AIO possui uma interface bastante estranha, por exemplo:

  • O único meio eficiente e bem suportado de retornos de chamada de eventos são os sinais, o que dificulta o uso em uma biblioteca, pois significa o uso de números de sinal do espaço de nomes de sinal global do processo. Se o seu sistema operacional não suportar sinais em tempo real, isso também significa que você precisará percorrer todas as solicitações pendentes para descobrir qual realmente terminou (é o caso do Mac OS X, por exemplo, não do Linux). A captura de sinais em um ambiente multithread também cria algumas restrições complicadas. Você normalmente não pode reagir ao evento dentro do manipulador de sinal, mas é necessário aumentar um sinal, gravar em um pipe ou usar signalfd () (no linux).
  • lio_suspend () tem os mesmos problemas que o select (), mas não se adapta muito bem ao número de trabalhos.
  • lio_listio (), conforme implementado, tem um número bastante limitado de tarefas que você pode passar, e não é trivial encontrar esse limite de maneira portátil. É necessário chamar sysconf (_SC_AIO_LISTIO_MAX), que pode falhar; nesse caso, você pode usar a definição AIO_LISTIO_MAX, que não é necessariamente definida, mas você pode usar 2, que é definido como garantido como suportado.

Quanto ao aplicativo do mundo real usando o posix AIO, você pode dar uma olhada no lighttpd (lighty), que também postou um medição de desempenho ao apresentar o suporte.

A maioria das plataformas posix suporta o posix AIO (Linux, BSD, Solaris, AIX, tru64). O Windows oferece suporte via E/S de arquivo sobreposto. Meu entendimento é que apenas o Solaris, Windows e Linux suportam verdadeiramente async. E/S de arquivo até o driver, enquanto os outros SOs emulam o assíncrono. E/S com threads do kernel. Sendo a exceção o Linux, sua implementação posix de AIO na glibc emula operações assíncronas com threads no nível do usuário, enquanto sua interface de E/S assíncrona nativa (io_submit () etc.) é verdadeiramente assíncrona até o driver, assumindo que o driver o suporte .

Eu acredito que é bastante comum entre os sistemas operacionais não oferecer suporte ao posix AIO para qualquer fd, mas restringi-lo a arquivos regulares.

69
Arvid

Um desenvolvedor da libtorrent fornece um relatório sobre isso: http://blog.libtorrent.org/2012/10/asynchronous-disk-io/

11
Allen

Existe aio_write - implementado no glibc; A primeira chamada da função aio_read ou aio_write gera uma série de solicitações de modo de usuário, aio_write ou aio_read publica solicitações para essa thread, a thread é pré-escrita/escrita e, quando finalizada, a resposta é postada novamente na thread de chamada bloqueada.

Também existe um aio 'real' - suportado pelo nível do kernel (precisa do libaio para isso, consulte a chamada io_submit http://linux.die.net/man/2/io_submit ); também precisa de O_DIRECT para isso (também pode não ser suportado por todos os sistemas de arquivos, mas os principais suportam)

veja aqui:

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

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

Diferença entre POSIX AIO e libaio no Linux?

2
MichaelMoser