在python中为大文件创建校验和的最快方法

时间:2009-10-07 16:28:08

标签: python multithreading md5 crc32 hashlib

我需要跨网络传输大文件,并且需要每小时为它们创建校验和。所以产生校验和的速度对我来说至关重要。

不知怎的,我不能让zlib.crc32和zlib.adler32在Windows XP Pro 64bit机器上使用大于4GB的文件。我怀疑我在这里达到了32位的限制?使用hashlib.md5我可以得到一个结果,但问题是速度。为4.8GB文件生成md5大约需要5分钟。任务管理器显示该进程仅使用一个核心。

我的问题是:

  1. 有没有办法让crc适用于大文件?我更喜欢使用crc而不是md5
  2. 如果没有,那么有没有办法加速md5.hexdigest()/ md5.digest?或者在这种情况下任何hashlib hexdigest / digest?可能将其拆分为多线程进程?我该怎么做?
  3. PS:我正在开发类似“资产管理”系统的东西,有点像svn,但资产包括大型压缩图像文件。文件有微小的增量变化。检测更改和错误检测需要哈希/校验和。

6 个答案:

答案 0 :(得分:4)

算法选择问题,而不是库/语言选择问题!

主要有两点需要考虑:

  • 磁盘I / O 对整体性能有多大影响?
  • 错误检测功能的预期可靠性是什么?

显然,第二个问题的答案就像'一些假否定',因为相对于4Gb消息,任何 32位哈希的可靠性,甚至在适度嘈杂的频道中,几乎不是绝对的。

假设可以通过多线程改进I / O,我们可以选择不需要对完整消息进行顺序扫描的哈希。相反,我们可以并行处理文件,散列各个部分并组合散列值或附加散列值,以形成更长,更可靠的错误检测设备。

下一步可能是将这种文件处理形式化为有序部分,并将其作为传输(在接收者端重新粘合在一起)。这种方法,以及有关文件生成方式的附加信息(例如,它们可能通过追加,例如日志文件进行排他性修改)甚至可以允许限制所需的哈希计算量。这种方法增加的复杂性需要加权,以满足快速CRC计算的需求。

附注:Alder32 仅限于特定阈值以下的邮件大小。它可能只是zlib API的限制。 (顺便说一句,我发现关于zlib.adler32的参考使用了一个缓冲区,而且......在我们的大量消息的上下文中要避免这种方法,支持流式处理:从文件中读取一些,计算,重复。 。)

答案 1 :(得分:2)

首先,任何CRC算法都没有固有的东西阻止它们处理任意长度的数据(但是,特定的实现可能会施加一个限制)。

但是,在文件同步应用程序中,这可能无关紧要,因为您可能不希望在文件变大时散列整个文件,无论如何都只是块。如果散列整个文件,并且每端的散列不同,则必须复制整个文件。如果您散列固定大小的块,那么您只需要复制散列已更改的块。如果对文件的大多数更改都是本地化的(例如数据库),那么这可能需要更少的复制(并且它更容易在多个核心上按照块计算进行传播)。

对于哈希算法本身,基本权衡是速度与缺少冲突(两个不同的数据块产生相同的哈希)。 CRC-32速度很快,但只有2 ^ 32个唯一值,可能会出现冲突。 MD5要慢得多,但是有2 ^ 128个唯一值,因此几乎从未见过碰撞(但理论上仍然可能)。较大的哈希值(SHA1,SHA256,...)具有更多独特的值,但速度更慢:我怀疑你需要它们:你担心意外碰撞,不像数字签名应用程序,你有意担心(恶意的设计碰撞。

听起来你正在尝试做一些与rsync实用程序非常相似的事情。你能使用rsync吗?

答案 2 :(得分:1)

您可能正在达到XP中文件的大小限制。 64位为您提供更多的寻址空间(每个应用程序移除2GB(左右)寻址空间),但可能无法解决文件大小问题。

答案 3 :(得分:0)

由于MD5的本质,你不可能使用多个核心来计算大文件的MD5哈希值:它希望消息以块的形式分解并以严格的顺序输入散列函数。但是,您可以使用一个线程将文件读入内部队列,然后在单独的线程中计算哈希值。我不认为这会给你带来任何显着的性能提升。

处理大文件需要这么长时间的事实可能是由于“无缓冲”读取。尝试一次读取16 Kb,然后将内容以块的形式提供给散列函数。

答案 4 :(得分:0)

md5本身不能并行运行。但是你可以在部分(并行)md5文件,并获取哈希列表的md5。

然而,假设散列不受IO限制,我怀疑它是。正如Anton Gogolev建议的那样 - 确保你正在有效地阅读文件(以2个大块的力量)。完成后,请确保文件没有碎片。

对于新项目,还应选择sha256之类的散列而不是md5。

对于4Gb文件,zlib校验和是否比md5快得多?

答案 5 :(得分:0)

您是否尝试过crc-generator模块?