【问题标题】:Hashlib: optimal size of chunks to be used in md5.update()Hashlib:要在 md5.update() 中使用的块的最佳大小
【发布时间】:2013-07-17 21:17:54
【问题描述】:

这是参考Get MD5 hash of big files in PythonHashlib in Windows and Linux

在回答这两个问题时,建议在函数 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?

【问题讨论】:

    标签: python md5 hashlib


    【解决方案1】:

    发现错误!我是reading 只是一个块然后什么都不做!

    改变了

    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 GB。这些文件中的每一个的 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是文件被打断成chuck并递增hash时的执行时间; 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

    【讨论】:

    • 为了好奇,您能告诉我们您发现的最佳块大小吗?
    • 随着块大小的增加,性能将逐渐增加到运行 md5 代码的系统的最大理论吞吐量。当您缓冲 1MiB 时,速度的任何提高早已变得无关紧要。如果您想选择任意缓冲区大小,我建议 128k。所有哈希函数都是如此。
    • @2rs2ts 最佳大小为 65536 字节。请参阅上面我的答案的更新。
    猜你喜欢
    • 2011-12-11
    • 1970-01-01
    • 2011-08-03
    • 2016-05-14
    • 1970-01-01
    • 2014-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多