C # высокоскоростной хэш MD5 / SHA по сети - PullRequest
1 голос
/ 20 января 2011

В проекте C #, над которым я сейчас работаю, мы пытаемся вычислить MD5 большого количества файлов по сети (текущий банк составляет 2,7 миллиона, клиентский банк может превышать 10 миллионов). С количеством файлов, которые мы обрабатываем, скорость имеет значение.

Причина, по которой мы это делаем, заключается в том, чтобы убедиться, что файл был скопирован в другое место без изменений.

В настоящее время мы используем следующий код для вычисления MD5 файла

MD5 md5 = new MD5CryptoServiceProvider();
StringBuilder sb = new StringBuilder();

byte[] hashMD5 = null;

try
{
   // Open stream to file to get MD5 hash for, create hash
   using (FileStream fsMD5 = new FileStream(sFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
      hashMD5 = md5.ComputeHash(fsMD5);
}
catch (Exception ex)
{
   clsLogging.logError(clsLogging.ErrorLevel.ERROR, ex);
}

string md5sum = "";
if (hashMD5 != null)
{
   // Change hash into readable text
   foreach (byte hex in hashMD5)
      sb.Append(hex.ToString("x2"));
    md5sum = sb.ToString();
}

Однако, скорость не та, на которую надеялся мой менеджер. Мы прошли через ряд изменений в способе и количестве файлов, для которых мы рассчитываем MD5 (т.е. мы не делаем это для файлов, которые мы не копируем ... до сегодняшнего дня, когда мой менеджер передумал так ВСЕМ файлам должен быть рассчитан MD5 для них, на случай, если в будущем клиент захочет работать с нашей программой, поэтому все файлы будут скопированы, я думаю)

Я понимаю, что скорость сети, вероятно, является основным фактором (100 Мбит / с). Есть ли эффективный способ расчета MD5 содержимого файла по сети?

Спасибо заранее. Тревор Уотсон

Редактировать: поместить весь код в блок, а не только его часть.

Ответы [ 3 ]

3 голосов
/ 20 января 2011

Узким местом является то, что весь файл должен быть передан / скопирован по сети, и ваш файл выглядит хорошо ... разные хеш-функции (md5 / sha256 / sha512) имеют практически одинаковое время вычисления

Два возможных решения этой проблемы:

1) запустите хешер в удаленной системе и сохраните хеш в отдельные файлы - если это возможно в вашей среде.

2) Создайте частичный хэш файла, чтобы вы копировали только часть файла. Я имею в виду что-то подобное:

part1Hash = md5(file.getXXXBytesFromFileAtPosition1)
part2Hash = md5(file.getXXXBytesFromFileAtPosition2)
part3Hash = md5(file.getXXXBytesFromFileAtPosition3)
finalHash = part1Hash ^ part2Hash ^ part3Hash;

Вы должны проверить, какая часть файла оптимальна для чтения, поэтому хэши остаются уникальными.

надеюсь, что это поможет ...

edit: изменено на побитовое xor

3 голосов
/ 20 января 2011

Один из возможных подходов - использовать библиотеку параллельных задач в .Net 4.0. Узкое место по-прежнему будет стоить 100 Мбит / с, но вы должны увидеть скромное улучшение.

В прошлом году я написал небольшое приложение, которое проверяет верхние уровни дерева папок, проверяя папку и настройки безопасности файлов. При работе в глобальной сети 10 Мбит / с на создание одного из наших общих файловых ресурсов ушло около 7 минут. Когда я распараллелил операцию, время выполнения уменьшилось до чуть более 1 минуты.

1 голос
/ 20 января 2011

Почему бы вам не попробовать установить «клиент» на каждом, который прослушивает порт и при получении сигнала вычислит хеш MD5 для запрошенных файлов.

Тогда главному серверу нужно будет только попросить каждого клиента рассчитать MD5. Используя этот распределенный подход, вы получите общую скорость всех клиентов и уменьшите перегрузку сети.

...