Eu tenho que sincronizar arquivos grandes em algumas máquinas. Os arquivos podem ter até 6 GB de tamanho. A sincronização será feita manualmente a cada poucas semanas. Não posso levar o nome do arquivo em consideração porque eles podem mudar a qualquer momento.
Meu plano é criar somas de verificação no PC de destino e no PC de origem e copiar todos os arquivos com uma soma de verificação, que ainda não está no destino, para o destino. Minha primeira tentativa foi algo assim:
using System.IO;
using System.Security.Cryptography;
private static string GetChecksum(string file)
{
using (FileStream stream = File.OpenRead(file))
{
SHA256Managed sha = new SHA256Managed();
byte[] checksum = sha.ComputeHash(stream);
return BitConverter.ToString(checksum).Replace("-", String.Empty);
}
}
O problema era o tempo de execução:
- com SHA256 com um arquivo de 1,6 GB -> 20 minutos
- com MD5 com um arquivo de 1,6 GB -> 6,15 minutos
Existe uma maneira melhor - mais rápida - de obter a soma de verificação (talvez com uma melhor função de hash)?
c#
.net
large-files
checksum
crono
fonte
fonte
Respostas:
O problema aqui é que
SHA256Managed
lê 4096 bytes de cada vez (herdaFileStream
e substituiRead(byte[], int, int)
para ver o quanto ele lê do fluxo de arquivos), que é um buffer muito pequeno para E / S de disco.Para acelerar as coisas (2 minutos para hash arquivo de 2 GB na minha máquina com SHA256, 1 minuto para MD5) envoltório
FileStream
emBufferedStream
e definir o tamanho do buffer de tamanho razoável (eu tentei com tampão de ~ 1 Mb):fonte
Não faça a soma de verificação do arquivo inteiro, crie somas de verificação a cada 100mb, aproximadamente, para que cada arquivo tenha uma coleção de somas de verificação.
Então, ao comparar somas de verificação, você pode parar de comparar após a primeira soma de verificação diferente, sair cedo e evitar que você processe o arquivo inteiro.
Ainda levará tempo integral para arquivos idênticos.
fonte
Como Anton Gogolev observou , o FileStream lê 4096 bytes por vez por padrão, mas você pode especificar qualquer outro valor usando o construtor FileStream:
Observe que Brad Abrams, da Microsoft, escreveu em 2004:
fonte
fonte
Invoque a porta do Windows do md5sum.exe . É cerca de duas vezes mais rápido que a implementação do .NET (pelo menos na minha máquina usando um arquivo de 1,2 GB)
fonte
Ok - obrigado a todos - deixe-me concluir:
fonte
Eu fiz testes com tamanho de buffer, executando este código
E eu testei com um arquivo de 29½ GB de tamanho, os resultados foram
Estou executando uma CPU i5 2500K, 12 GB de RAM e uma unidade SSD OCZ Vertex 4 256 GB.
Então eu pensei, que tal um disco rígido padrão de 2 TB. E os resultados foram assim
Então, eu recomendaria nenhum buffer ou um buffer de no máximo 1 moinho.
fonte
Você está fazendo algo errado (provavelmente um buffer de leitura muito pequeno). Em uma máquina com idade indecente (Athlon 2x1800MP de 2002) que possui DMA no disco provavelmente fora de sintonia (6.6M / s é muito lento ao fazer leituras sequenciais):
Crie um arquivo 1G com dados "aleatórios":
1m5.299s
1m58.832s
Isso também é estranho, o md5 é consistentemente mais lento que o sha1 para mim (execute novamente várias vezes).
fonte
Sei que estou atrasado para a festa, mas realizei o teste antes de realmente implementar a solução.
Eu realizei teste contra a classe MD5 embutida e também o md5sum.exe . No meu caso, a classe incorporada levou 13 segundos, enquanto o md5sum.exe também ficou em torno de 16 a 18 segundos em cada execução.
fonte
Você pode dar uma olhada no XxHash.Net ( https://github.com/wilhelmliao/xxHash.NET )
O algoritmo do xxHash parece ser mais rápido que todos os outros.
Alguma referência no site xxHash: https://github.com/Cyan4973/xxHash
PS: Eu ainda não o usei.
fonte