【问题标题】:How do I replace the Python Build-in method, with a 3rd party installed module instead?如何用第 3 方安装的模块替换 Python 内置方法?
【发布时间】:2019-07-11 18:08:17
【问题描述】:

我正在优化我的代码并将 Python 内置 hashlib.pbkdf2_hmac 替换为快 40% 的 Fast PBKDF2 实现 python-fastpbkdf2

但是使用 cProfile 的结果似乎是一样的。

我已经(尝试)确保使用 Fast PBKDF2 模块而不是内置的 hashlib.pbkdf2_hmac 模块,但我似乎不明白为什么我没有看到 40% 的性能提升。

from fastpbkdf2 import pbkdf2_hmac

phrase_words = "clerk great coin mistake become"
passphrase = 'passphrase'

seed = pbkdf2_hmac('sha512', bytes(complete_phrase_words, encoding='utf-8'), bytes('mnemonic' + passphrase, encoding='utf-8'), 2048)

如何确保不使用内置方法?

cProfile 报告:

186811385 function calls (186811349 primitive calls) in 885.041 seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
   109344  710.505    0.006  710.505    0.006 {built-in method _fastpbkdf2.fastpbkdf2_hmac_sha512}
 57919431   54.060    0.000   54.060    0.000 {built-in method builtins.format}
 57918564   45.288    0.000  116.547    0.000 crypto_awesomer_fast_pbkdf2_test.py:75(<genexpr>)
  3619696   20.854    0.000  137.401    0.000 {method 'join' of 'str' objects}
 57919431   20.604    0.000   20.604    0.000 {method 'zfill' of 'str' objects}
  1755108   14.666    0.000  877.752    0.001 crypto_awesomer_fast_pbkdf2_test.py:66(validate)
  1755108    4.119    0.000    4.119    0.000 {method 'to_bytes' of 'int' objects}
  1755108    3.949    0.000    3.949    0.000 {method 'digest' of '_hashlib.HASH' objects}
        1    3.825    3.825  884.982  884.982 crypto_awesomer_fast_pbkdf2_test.py:33(nested_loops)
  1755109    2.859    0.000    2.859    0.000 {built-in method _hashlib.openssl_sha256}
   109344    1.937    0.000  714.213    0.007 crypto_awesomer_fast_pbkdf2_test.py:89(generate_seed)
   109344    1.315    0.000  712.156    0.007 __init__.py:18(pbkdf2_hmac)


【问题讨论】:

  • 您是否安装了 OpenSSL? Python 使用 OpenSSL 提供的快速实现(如果可用,而不是内置实现),也许这就是您看不到速度差异的原因。似乎 python-fastpbkdf2 多年来没有更新,我会对他们的基准测试持保留态度。
  • 确实如此。如果没有 OpenSSL,Fast PBKDF2 模块给了我“致命错误:找不到‘openssl/sha.h’文件”,我通过使用“brew install openssl”和“brew link --force openssl”安装 OpenSSL 解决了这个问题。

标签: python pbkdf2


【解决方案1】:

您确实使用了 Fast PBKDF2 模块,如 cProfile 输出所示。

我猜python-fastpbkdf2 所做的任何性能测量都在与旧版本的 Python、OpenSSL 或两者进行比较,而新版本的速度赶上了(而 Fast PBKDF2 在三年多的时间里没有看到更新) .碰巧的是,它看起来像 2016 年(Fast PBKDF2 看到其最后一次更新的一年后),Python added a fast path when linked against OpenSSL 1.1.0 or higher that uses OpenSSL's optimized PKCS5_PBKDF2_HMAC,而不是 Python 的本土(较慢)版本。甚至在那之前,Python had improved their homegrown version back in late 2013;如果在改进发布之前运行python-fastpbkdf2 基准测试,性能会差很多。

基本上,不要假设速度快 40% 的说法是正确的,即使它们在过去是正确的(也不能保证它们在过去也是正确的)。

也有可能编译器和/或您的软件包仓库维护者构建了更好的 OpenSSL 版本;至少 Fast PBKDF2 声称的好处之一是他明确地内联了许多操作,但是使用 PGO+LTO 正确编译的 OpenSSL 版本无论如何都能够自动内联适当的操作(如果 @987654327 的设置文件@ 没有使用 PGO+LTO 正确构建它,因此可能会丢失)。在这与 OpenSSL 进行类似的代码改进之间,差距很容易缩小。

【讨论】:

  • 非常感谢!有没有办法确认我使用的 OpenSSL 版本是否是使用 PGO+LTO 正确编译的 OpenSSL 版本?
  • 如何确认Python内置hashlib.pbkdf2_hmac是否使用了安装的OpenSSL?
  • @rphessing:可以用import sslprint(ssl.OPENSSL_VERSION)查看Python链接的OpenSSL版本号;任何 1.1.0 或更高版本都将使用快速路径。如果 Python 恰好链接到系统 openssl,您可以使用 openssl version -f 检查 openssl 的构建标志;在我的 Ubuntu 构建中,它看起来不像使用 PGO 或 LTO,但 OpenSSL 完全有可能在 Python 1.1.0 使用的快速路径中进行了与 Fast PBKDF2 相同的手动改进,因此它可能不需要它。
猜你喜欢
  • 1970-01-01
  • 2021-06-07
  • 2020-10-02
  • 2017-07-08
  • 2020-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-26
相关资源
最近更新 更多