5

これは、Python で大きなファイルの MD5 ハッシュを取得し、Windows と LinuxでHashlib を参照しています。

これら両方の質問への回答として、関数 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 バイト)を使用すると最高のパフォーマンスが得られることが示されています。

引用された質問に示されているものとは異なる結果が表示される理由は何ですか?

サイズが700MBから1.2GBのバイナリおよびプレーンテキストファイルを試し、Ubuntu 12.04でPython 2.7.3を使用しています

二次的な質問: timeit を正しい方法で使用していますか?

4

1 に答える 1

6

エラーを発見!私はread1 つのチャンクだけを ing してから何もしませんでした!

かわった

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() をインクリメンタルに使用して特定のファイルのハッシュを見つけるときに使用するバッファの最適なサイズを確立するために、上記のプログラムをわずかに変更したバージョンを実行しました。また、ファイルのハッシュを一度に計算するのではなく、増分ハッシュに利点があるかどうかを確認したかった (メモリの制約以外)。

このために、ファイル サイズが 4096 バイトから始まり、最大 2.1 GB の 20 個のファイル (ランダム データを含む) を作成しました。これらの各ファイルの md5 ハッシュは、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ファイルがチャックに分割され、インクリメンタルにハッシュされる実行時間です。これComplete Timeは、ファイル全体が一度にハッシュされる実行時間です。これ%diffは、チャンク時間と「完了時間」のパーセンテージ差です。

所見:

  1. ファイル サイズが小さい場合、チャンク サイズはほぼ常にファイル サイズと同じであり、どちらのアプローチを採用しても利点はないようです。
  2. 大きなファイル (33554432 ( 2**25) バイト以上) の場合、ファイル全体を一度にハッシュするよりも、インクリメンタル アプローチを使用すると、かなりのパフォーマンス上の利点 (時間の短縮) があるようです。
  3. 大きなファイルの場合、最適なチャンク/バッファ サイズは 65536 ( 2**16) バイトです。

注: python 2.7.3; Ubuntu 12.06 64 ビット; 8 GB の RAM これに使用されるコードは、ここから入手できます... http://pastebin.com/VxH7bL2X

于 2013-07-19T16:44:55.907 に答える