Сброс физического диска в файл и одновременное его хеширование - PullRequest
0 голосов
/ 22 апреля 2011

Я создал приложение WPF, которое считывает физическое устройство (жесткий диск, USB-накопитель) в файл. Я получаю скорость до 75-80 МБ / с для HD и 20-25 для USB. Я хотел добавить MD5 и SHA1 хэширование изображения на лету. Обычно я считываю блок из 128 секторов (64 КБ) с диска, хеширую его с помощью двух алгоритмов, а затем записываю блок в другой файл.

Что ж, две функции хеширования кажутся огромным узким местом. Скорость снизилась до 5 Мбит / с для USB и 20 Мбит / с для HD.

Итак, я попытался поместить код хэширования в другой поток. Таким образом, один поток читает блоки и помещает значение в список FIFO (созданный с использованием List). Затем другой поток выскакивает блок и использует его. Проблема в том, что чтение потока с диска происходит быстрее, чем хэширование, и список будет расти в геометрической прогрессии. Поэтому я поставил ограничение в списке из 1024 блоков. Когда первый поток видит, что в списке 1024 блока или более, он спит, пока не достигнет 512 ...

Кажется, это работает в течение первых нескольких секунд. Я получаю 19 Мбит / с для USB. Но через некоторое время он снова начинает замедляться. Я полагаю, он заполнил список и ждет, пока у него будет свободное место ...

Может быть, у меня медленные функции? Я скопировал первое, что я нашел в Интернете ... Как я могу повысить скорость моего приложения?

Спасибо

Ответы [ 3 ]

1 голос
/ 22 апреля 2011

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

Предположительно, если у вас есть два потока, обращающихся к одному списку (лучше может быть Queue или ConcurrentQueue), у вас есть некоторые блокировки вокруг него.Вы уверены, что долго не удерживаете блокировку в одном потоке, поэтому другой поток блокируется?

В идеале вам нужно запустить какой-нибудь профилировщик, но вы можете использовать секундомери некоторые следы, чтобы выяснить, что происходит.

0 голосов
/ 22 апреля 2011

Это относительно простая, но интересная головоломка с производительностью, не так ли?

Для меня это звучит так, словно у вас узкое место в процессоре реализации алгоритма хеширования. Для эффективного алгоритма хеширования вместо простого копирования чего-либо случайного используйте стандартные классы в System.Security.Cryptography, такие как SHA1CryptoServiceProvider и MD5CryptoServiceProvider.

Если у вас есть несколько доступных ядер, рассмотрите возможность разделения хеширования на отдельные потоки. Как правило, для n ядер * используются потоки n+1; Если у вас есть многопоточные ядра (например, Intel HT), вы можете увеличить или уменьшить производительность, используя их. Task Parallel Library может помочь с этим , тем более что входной цикл чтения можно легко переписать как итератор .


* Например, на чипе Pentium IV Prescott производительность примерно на 10% теряется при использовании обоих ядер в стандартном клиенте Bitcoin, который в основном находится в цикле, где выполняются хэши.

0 голосов
/ 22 апреля 2011

Вы можете попробовать некриптографические хеш-функции здесь
Они должны быть быстрее криптографических

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...