我目前的做法是这样的:
def get_hash(path=PATH, hash_type='md5'):
func = getattr(hashlib, hash_type)()
with open(path, 'rb') as f:
for block in iter(lambda: f.read(1024*func.block_size, b''):
func.update(block)
return func.hexdigest()
Run Code Online (Sandbox Code Playgroud)
在 i5 @ 1.7 GHz 上计算 842MB iso 文件的 md5sum 大约需要 3.5 秒。我尝试了不同的读取文件的方法,但所有这些方法都会产生较慢的结果。也许有更快的解决方案?
编辑:我用 替换了2**16
(在 内f.read()
)1024*func.block_size
,因为block_size
hashlib 支持的大多数散列函数的默认值是64
(除了 'sha384' 和 'sha512' - 对于它们,默认值block_size
是128
)。因此,块大小仍然相同(65536 位)。
编辑(2):我做错了什么。它需要 8.4 秒而不是 3.5 秒。:(
编辑(3):当我再次运行该函数时,显然 Windows 正在以 +80% 的速度使用磁盘。真的需要3.5秒。呼。
另一个解决方案(~-0.5 秒,稍微快一点)是使用 os.open():
def get_hash(path=PATH, hash_type='md5'):
func = getattr(hashlib, hash_type)()
f = os.open(path, (os.O_RDWR | os.O_BINARY))
for block in iter(lambda: os.read(f, 2048*func.block_size), b''):
func.update(block)
os.close(f)
return func.hexdigest()
Run Code Online (Sandbox Code Playgroud)
请注意,这些结果不是最终结果。
使用 openssl 工具需要 2 秒的 874 MiB 随机数据文件,md5
我能够提高速度,如下所示。
def md5_speedcheck(path, size):
pts = time.process_time()
ats = time.time()
m = hashlib.md5()
with open(path, 'rb') as f:
b = f.read(size)
while len(b) > 0:
m.update(b)
b = f.read(size)
print("{0:.3f} s".format(time.process_time() - pts))
print("{0:.3f} s".format(time.time() - ats))
Run Code Online (Sandbox Code Playgroud)
人类时间就是我上面提到的。而所有这些的处理器时间大致相同,只是 IO 阻塞有所不同。
这里的关键决定因素是缓冲区大小足够大以减轻磁盘延迟,但又足够小以避免虚拟机页面交换。对于我的特定机器来说,64 KiB 似乎是最佳选择。