使用不同版本的sha哈希(hashlib模块)是否会造成显著的开销?

18

hashlib Python模块提供以下哈希算法构造器:md5()sha1()sha224()sha256()sha384()sha512()

假设我不想使用md5,那么使用sha1sha512相比,是否有很大的区别?我想使用类似于hashlib.shaXXX(hashString).hexdigest()的东西,但是由于只是用于缓存,我不确定是否需要(最终)额外的512开销...

这种开销是否存在,如果存在,它有多大?


2
如果是为了缓存,为什么需要安全哈希呢? - President James K. Polk
4
当您尝试不同的方法并测量它们的表现时,您发现了什么? - Greg Hewgill
2
@GregHewgill 可能想说的是,有一个方便的标准库模块 timeit,使得这样的测量如此简单,以至于直接计时比询问更容易,特别是当它从命令行运行时。 - Peter Hansen
@GregS,如果不使用安全哈希,你会用什么?我需要一个 Python 字典的指纹(包含搜索参数),以便确定(1)是否已经执行过此搜索,以及(2)如果是新搜索,则搜索结果是否可供显示。 - Emilien
1
我听从sttwister的意见。由于我从这次交流中学到了一些东西,所以我会点赞这个问题。 - President James K. Polk
2个回答

23
为什么不进行基准测试呢?
>>> def sha1(s):
...     return hashlib.sha1(s).hexdigest()
...
>>> def sha512(s):
...     return hashlib.sha512(s).hexdigest()
...
>>> t1 = timeit.Timer("sha1('asdf' * 100)", "from __main__ import sha1")
>>> t512 = timeit.Timer("sha512('asdf' * 100)", "from __main__ import sha512")
>>> t1.timeit()
3.2463729381561279
>>> t512.timeit()
6.5079669952392578

所以在我的机器上,hash512 的速度是 sha1 的两倍。但正如GregS所说,为什么要在缓存中使用安全哈希呢?尝试使用内置的哈希算法,它们应该非常快且经过调整:

>>> s = "asdf"
>>> hash(s)
-618826466
>>> s = "xxx"
>>> hash(s)
943435
>>> hash("xxx")
943435

或者更好的方法是使用Python内置字典。也许您可以告诉我们更多关于您计划缓存的内容。

编辑: 我想您正在尝试实现类似于这样的功能:

hash = hashlib.sha1(object_to_cache_as_string).hexdigest()
cache[hash] = object_to_cache

我所指的“使用Python内置字典”是指您可以简化上述内容:

cache[object_to_cache_as_string] = object_to_cache

这样一来,Python会处理散列,因此您不必担心!关于您的特定问题,您可以参考Python可散列字典以使字典可散列。然后,您只需执行以下操作即可缓存对象:
cache[object_to_cache] = object_to_cache

编辑 - 关于 Python3 的说明

Python 3.3 引入了哈希随机化,这意味着计算出的哈希值可能在不同的进程中不同,因此您不应该依赖计算出的哈希值,除非将 PYTHONHASHSEED 环境变量设置为 0。

参考: - https://docs.python.org/3/reference/datamodel.html#object.hash - https://docs.python.org/3/using/cmdline.html#envvar-PYTHONHASHSEED


感谢您抽出时间进行基准测试。正如你们中的许多人所说,我可能不需要在缓存中使用安全哈希。基本上,我需要存储字典内容的指纹。由于我不能直接在字典上使用hashlibhash(),因此我正在构建一个包含该字典元素的字符串(不喜欢这种方法),然后对其使用hashlib...但现在你用“使用内置的Python字典”激起了我的好奇心,你是什么意思? - Emilien
通过阅读你们的评论,我意识到我不需要使用任何安全哈希算法,因此我实现了自己的“哈希”算法。由于字典总是具有特定元素,并且每个值都有一个想法,所以我从这些想法中创建一个字符串并缓存它。感谢大家。 - Emilien
19
注意,如果你正在使用分布式平台并尝试生成缓存键等内容,则查看此答案建议使用hash()而不是hashlib进行非加密哈希的建议:请记住,在Python 3和某些Python 2的实现中,hash()在不同实例之间不返回一致的值,因此可能会出现问题。例如,Heroku上的每个“dyno”(例如Linux实例)似乎对相同字符串的hash()返回不同的结果。它仅在实例内部保持一致。据报道,GAE也具有类似的行为。 - B Robster

6
也许这是一个天真的测试...但看起来它取决于你哈希的数量。两个sha512块比四个sha256块要快?
>>> import timeit
>>> import hashlib
>>> for sha in [ x for x in dir(hashlib) if x.startswith('sha') ]:
...   t = timeit.Timer("hashlib.%s(data).hexdigest()" % sha,"import hashlib; data=open('/dev/urandom','r').read(1024)")
...   print sha + "\t" + repr(t.timeit(1000))
...
sha1    0.0084478855133056641
sha224  0.034898042678833008
sha256  0.034902095794677734
sha384  0.01980900764465332
sha512  0.019846916198730469

我得到了类似的结果。我认为这里的事实学习是,md5和sha1在速度上相似(我也使用了这种方法来进行基准测试),然后sha512比中间所有哈希都要快。因此,为了提高速度,请使用sha1,而为了更好的哈希,请使用sha512。从性能角度来看,其他哈希值没有意义。 - Adam Nelson
我得到了非常不同的结果,也许当前的实现或机器已经更好地优化了: sha10.00902104377746582 sha2240.007354021072387695 sha2560.007508993148803711 sha3840.004772186279296875 sha5120.004884004592895508 - user

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接