2013-07-18 3 views
3

Это ссылка на Get MD5 hash of big files in Python и Hashlib in Windows and LinuxHashlib: оптимальный размер кусков, которые будут использоваться в md5.update()

В ответах на оба эти вопроса, рекомендуется использовать большие массивы данных в функции md5 .update() для повышения производительности.

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

Рассмотрим следующий код:

def test(factor): 
    filehash = hashlib.md5() 
    blk_size_to_read = filehash.block_size * (2**factor) 
    with open(largetestfile, 'rb') as f: 
     read_data = f.read(blk_size_to_read) 
     filehash.update(read_data) 
    filehash.digest() 

if __name__ == '__main__': 
    for ctr in xrange(0, 12): 
     funcstr = "test({})".format(str(ctr)) 
     timetaken = timeit.timeit(funcstr, setup="from __main__ import test", number = 5000) 
     print "Factor: {} Time: {}".format(str(ctr), str(timetaken)) 

Все тесты, которые я сделал, показывают, что наилучшая производительность достигается при использовании factor 0 или 1 (то есть, 64 или 128 байт).

Любая причина, по которой я вижу разные результаты, указанные в указанных цитатах?

Я попытался бинарные и текстовые файлы с размером от 700Мб до 1.2GB и я использую Python 2.7.3 на Ubuntu 12.04

Вторичный вопрос: я использую timeit, как это должно быть?

ответ

3

Обнаружили ошибку! Я был read всего одним куском, а затем ничего не делал!

Изменено

with open(largetestfile, 'rb') as f: 
    read_data = f.read(blk_size_to_read) 
    filehash.update(read_data) 

в

with open(testfile, 'rb') as f: 
    while (True): 
     read_data = f.read(blk_size_to_read) 
     if not read_data: 
      break 
     filehash.update(read_data) 

, чтобы решить проблему.

UPDATE:

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

Я создал 20 файлов (со случайными данными) для этого с размером файла, начиная с 4096 байт и до 2,1 ГБ. mh5 хэш для каждого из этих файлов был рассчитан с использованием размеров буфера, начиная с 2**6 байт (64 байта - размер блока) до 2**20 байтов. Используя timeit, каждый из них выполнялся 100 раз и время выполнения, полученное с самым коротким временем выполнения записи. Также было записано время выполнения для вычисления хэша всего файла за один раз.

Результаты таковы ...

FileName   Filesize  Chunksize  Chunked Time Complete Time  %diff 
file5.txt     4096   4096  0.0014789  0.0014701   -0.60% 
file6.txt     8192   524288  0.0021310  0.0021060   -1.19% 
file7.txt    16384   16384  0.0033200  0.0033162   -0.12% 
file8.txt    32768   65536  0.0061381  0.0057440   -6.86% 
file9.txt    65536   65536  0.0106990  0.0112500   4.90% 
file10.txt    131072   131072  0.0203800  0.0206621   1.37% 
file11.txt    262144   524288  0.0396681  0.0401120   1.11% 
file12.txt    524288  1048576  0.0780780  0.0787551   0.86% 
file13.txt    1048576  1048576  0.1552539  0.1564729   0.78% 
file14.txt    2097152   262144  0.3101590  0.3167789   2.09% 
file15.txt    4194304   65536  0.6295781  0.6477270   2.80% 
file16.txt    8388608   524288  1.2633710  1.3030031   3.04% 
file17.txt   16777216   524288  2.5265670  2.5925691   2.55% 
file18.txt   33554432   65536  5.0558681  5.8452392   13.50% 
file19.txt   67108864   65536  10.1133211  11.6993010   13.56% 
file20.txt   134217728   524288  20.2226040  23.3923230   13.55% 
file21.txt   268435456   65536  40.4060180  46.6972852   13.47% 
file22.txt   536870912   65536  80.9403431  93.4165111   13.36% 
file23.txt   1073741824   524288 161.8108051 187.1303582   13.53% 
file24.txt   2147483648   65536 323.4812710 374.3899529   13.60% 

Chunked Time время выполнения, когда файл разбивается на патроне и hased постепенно; Complete Time - это время выполнения, когда весь файл хэшируется за один раз. %diff - это процентная разница между часовым временем и «полным временем».

Наблюдения:

  1. Для уменьшения размера файла размеры размер куска почти всегда равен размер файла и, кажется, нет никаких преимуществ в принятии любой подход.
  2. Для более крупных файлов (33554432 (2**25)) и выше, по сравнению с хешированием всего файла за один раз кажется значительным выигрыш в производительности (меньшее время).
  3. Для больших файлов это лучший размер блока/буфера 65536 (2**16) байт

Примечания: Python 2.7.3; Ubuntu 12.06 64 бит; 8 ОЗУ ОЗУ Код, используемый для этого, доступен здесь ... http://pastebin.com/VxH7bL2X

+0

Для любопытства вы можете рассказать нам, что вы нашли оптимальным размером куска? – 2rs2ts

+0

Производительность будет асимптотически увеличиваться в сторону максимального теоретического уровня вашей системы, запускающей код md5 по мере увеличения размера вашего куска. К тому времени, когда вы буферизируете 1MiB, любое увеличение скорости уже давно стало неуместным. Если вы хотите выбрать произвольный размер буфера, я предлагаю 128k. Это относится ко всем хэш-функциям. – gps

+1

@ 2rs2ts оптимальный размер - 65536 байт. См. Обновление моего ответа выше. – Verma

Смежные вопросы