Мне нужно синхронизировать большие файлы на некоторых машинах. Файлы могут иметь размер до 6 ГБ. Синхронизация будет выполняться вручную каждые несколько недель. Я не могу принять во внимание имя файла, потому что оно может измениться в любое время.
Мой план состоит в том, чтобы создать контрольные суммы на конечном ПК и на исходном ПК, а затем скопировать все файлы с контрольной суммой, которых еще нет в месте назначения, в место назначения. Моя первая попытка была примерно такой:
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);
}
}
Проблема заключалась во времени выполнения:
- с SHA256 с файлом 1,6 ГБ -> 20 минут
- с MD5 с файлом 1,6 ГБ -> 6,15 минут
Есть ли лучший и более быстрый способ получить контрольную сумму (возможно, с лучшей хеш-функцией)?
c#
.net
large-files
checksum
Хроно
источник
источник
Ответы:
Проблема здесь в том, что
SHA256Managed
за один раз читается 4096 байт (наследоватьFileStream
и переопределять,Read(byte[], int, int)
чтобы увидеть, сколько он читает из файлового потока), что является слишком маленьким буфером для дискового ввода-вывода.Для ускорения (2 минуты для хеширования 2 Гб файла на моей машине с SHA256, 1 минутой для MD5) обертывания
FileStream
вBufferedStream
и установить разумно размер размер буфера (я пробовал с ~ 1 Мб буферами):источник
Не используйте контрольную сумму для всего файла, создавайте контрольные суммы каждые 100 МБ или около того, чтобы каждый файл имел набор контрольных сумм.
Затем при сравнении контрольных сумм вы можете прекратить сравнение после первой другой контрольной суммы, выйти раньше и избавить вас от обработки всего файла.
Для идентичных файлов все равно потребуется полное время.
источник
Как заметил Антон Гоголев , FileStream по умолчанию читает 4096 байт за раз, но вы можете указать любое другое значение с помощью конструктора FileStream:
Обратите внимание, что Брэд Абрамс из Microsoft писал в 2004 году:
источник
источник
Вызовите порт Windows для md5sum.exe . Это примерно в два раза быстрее, чем реализация .NET (по крайней мере, на моей машине с файлом размером 1,2 ГБ)
источник
Хорошо - спасибо всем - позвольте мне подвести итог:
источник
Я провел тесты с размером буфера, запустив этот код
Я тестировал файл размером 29½ ГБ, результаты были
Я использую процессор i5 2500K, 12 ГБ оперативной памяти и SSD-диск OCZ Vertex 4 256 ГБ.
Я подумал, а как насчет стандартного жесткого диска на 2 ТБ. И результаты были такими
Поэтому я бы рекомендовал либо без буфера, либо с буфером не более 1 миллиметра.
источник
Вы делаете что-то не так (вероятно, слишком маленький буфер чтения). На машине незрелого возраста (Athlon 2x1800MP от 2002 года), на диске которой есть DMA, вероятно, неисправен (6,6 Мбит / с чертовски медленно при последовательном чтении):
Создайте файл размером 1G со «случайными» данными:
1m5.299s
1m58.832s
Это тоже странно, md5 для меня постоянно медленнее, чем sha1 (несколько раз перезапущен).
источник
Я знаю, что опаздываю на вечеринку, но провел тест, прежде чем фактически реализовать решение.
Я провел тест со встроенным классом MD5, а также с md5sum.exe . В моем случае встроенный класс занимал 13 секунд, а md5sum.exe тоже около 16-18 секунд при каждом запуске.
источник
Вы можете взглянуть на XxHash.Net ( https://github.com/wilhelmliao/xxHash.NET )
. Алгоритм xxHash кажется быстрее, чем все остальные.
Некоторые тесты на сайте xxHash: https://github.com/Cyan4973/xxHash
PS: Еще не пользовался.
источник