Pergunta

Tenho um pequeno programa que lê e grava arquivos no disco.Quebrá-lo para baixo para o nível mais simples, ele lê bytes de um fluxo de arquivos e grava-los para outra.Ele executa suas funções muito bem, mas ele não é a coisa mais rápida.

Eu já vi outros aplicativos que podem romper-se através de um ou mais gigabytes de leituras/gravações em velocidades incríveis.É óbvio que eles estão operando mais próximo do metal do que um pouco .NET app.

O que são as mais eficientes .APIs de rede para streaming de/para o disco?O que win32 APIs estão disponíveis (e vale p/a invocação para) para rápido acesso a disco?

Foi útil?

Solução

Rápido e/S de arquivo é menos sobre o específico chamadas de API que você faz, mas sim sobre como você projetar seu aplicativo para trabalhar com I/O.

Se você estiver executando todas as suas operações de e/S em um único segmento de uma forma sequencial, por exemplo

  1. Bloco de leitura na memória
  2. Processo bloco de memória, de alguma forma,
  3. Bloco de gravação para arquivo
  4. Repita até terminar...

você está gargalos do sistema de e/S de largura de banda do loop de processamento de um único segmento.Uma alternativa, mas mais complicado design é multithread sua aplicação para maximizar a produtividade e evitar o tempo de espera.Isto permite que o sistema para aproveitar tanto o CPU e de e/S de largura de banda do controlador simultaneamente.Um típico projeto para este ficaria algo como:

  1. Um (ou mais) threads de trabalho de leitura de dados a partir do disco e adicioná-los a uma casa de fila de entrada
  2. Um (ou mais) threads de trabalho de leitura de blocos de partilhada fila de entrada, processá-los e adicioná-los a uma casa de fila de saída
  3. Um (ou mais) threads de trabalho de leitura processados bloqueado compartilhado fila de saída e escreve para o adequado arquivos de saída.

Isso não é fácil de arquitectura para o design de direito, e requer um pouco de pensamento para evitar a criação de memória de contenção de bloqueio, ou sobrecarregar o sistema com simultâneas solicitações de e/S.Você também precisará fornecer controle de metadados, de modo que o estado de processamento de saída não é gerenciado na pilha de chamada de uma linha, mas sim na entrada/saída de filas de trabalho.Você também tem que se certificar de que você transformação e escrever o resultado na ordem correta, pois com multi-thread de e/S que você não pode ter certeza de que o trabalho é colocado na fila de entrada em uma ordem garantida.É complicado, mas é possível, e ele pode ter uma diferença dramática na taxa de transferência através de uma série de abordagem.

Se você realmente tiver tempo e quiser espremer cada gota de desempenho do sistema, você também pode usar Conclusão de e/S portas - um relativamente baixo nível de API, para maximizar a taxa de transferência.

Boa sorte.

Outras dicas

O suporte do arquivo .NET é rápido o suficiente (comparável às funções nativas do Win32). Várias opções que podem ajudá -lo a melhorar seu desempenho:

  1. Se a sua leitura/gravação for seqüencial, ajude o gerente de cache aplicando a estratégia apropriada - forneça RandomAccess ou Sequentalscan, ao instanciar o FileStream
  2. Considere usar um buffer de memória maior para armazenar dados de leitura
  3. Se você copiar muitos arquivos pequenos, poderá primeiro ler muitos arquivos em um buffer de memória de uma só vez (consulte 2) e depois escreva os arquivos no disco
  4. Se os fluxos de origem e destino estiverem localizados em lugares diferentes (ou seja, não no mesmo disco rígido, talvez um arquivo na rede, o outro em um disco rígido local etc.), você pode usar o padrão assíncrono para acelerar , leia dados usando BEGIN LREAD, então escreva dados usando BeginWrite, e enquanto os dados estão sendo escritos, leia o próximo bloco de dados usando o BEGINRAD.
  5. Se você ainda acha que o desempenho não é suficiente (no entanto, do meu teste, é equatável ou ainda mais rápido que a cópia do Windows interna), você pode usar o CopyFileEx Função Win32 (mas essa função funciona com arquivos, não fluxos).

Você apresentou um perfil de seu aplicativo para determinar se a E/S do disco era o gargalo?

Em que tipo de hardware você está executando isso? Qual é a configuração de hardware?

Em .net você pode tentar o System.IO.File espaço para nome.

Para funções Win32, você pode experimentar a série CreateFile, Writefile e ReadFile.

Um exemplo:

http://msdn.microsoft.com/en-us/library/bb540534(vs.85).aspx

Definitivamente, isso não é cortado e seco. É tudo sobre testar e medir.

BinaryReader e BinaryWriter Com um tamanho de buffer adequado, é muito rápido. Se você está lendo em estruturas, a abordagem insegura descrita neste artigo Vai fazer você ler rapidamente, e escrever é semelhante. Também concordo com a sugestão de verificar se a E/S é realmente o gargalo. Eu me deparei com esse artigo devido a esse erro.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top