python - cProfile 需要很长时间

标签 python cprofile

我开始使用 cProfile 来分析我的 python 脚本。 我注意到一些非常奇怪的事情。

当我使用 time 来测量我的脚本的运行时间时,它需要 4.3 秒。

当我使用 python -m cProfile script.py 时,它需要 7.3 秒。

在代码中运行探查器时:

import profile
profile.run('main()')

需要 63 秒!!

我能理解为什么在添加分析时可能需要更多时间,但为什么从外部使用 cProfile 或作为代码的一部分会有如此大的区别? 为什么我使用 profile.run 时需要这么多时间?

最佳答案

奇怪的是,您看到的是预期的行为。在introduction to the profilers在 Python 文档的一部分中,它指出与 cProfile 相比,profile 增加了“对分析程序的显着开销”。您看到的区别在于您使用的库,而不是您如何调用它们。考虑这个脚本:

import profile
import cProfile

def nothing():
    return

def main():
    for i in xrange(1000):
        for j in xrange(1000):
            nothing()

    return

cProfile.run('main()')
profile.run('main()')

cProfile 的输出显示 main 运行大约需要 0.143 秒,而 profile 变体报告为 1.645 秒,长约 11.5 倍。

现在让我们再次将脚本更改为:

def nothing():
    return

def main():
    for i in xrange(1000):
        for j in xrange(1000):
            nothing()

    return

if __name__ == "__main__":
    main()

然后用分析器调用它:

python -m profile test_script.py

报告主要运行时间为 1.662 秒。

python -m cProfile test_script.py

报告主要运行时间为 0.143 秒。

这表明您启动分析器的方式与您在 cProfileprofile 之间看到的差异无关。不同之处在于两个分析器如何处理函数调用或返回等“事件”。在这两种情况下,您的执行代码中都有软件 Hook ,这些 Hook 会触发回调以跟踪这些事件并执行更新事件计数器以及启动或停止计时器等操作。但是,profile 模块在 Python 中本地处理所有这些事件,这意味着您的解释器必须离开您的代码,执行回调内容,然后返回以继续您的代码.

cProfile 也会发生同样的事情(执行分析回调),但速度要快得多,因为回调是用 C 语言编写的。看一下两个模块文件 profile.py cProfile.py 展示了一些差异:

  1. profile.py 有 610 行,而 cProfile.py 只有 199 行 - 它的大部分功能都是用 C 语言处理的。
  2. profile.py 主要使用 Python 库,而 cProfile.py 导入 C 代码文件“_lsprof”。源码可以查看here .
  3. profile.py 中的 Profile 类不继承任何其他类(第 111 行),而 Profile 类在 < strong>cProfile.py(第66行)继承自_lsprof.Profiler,在C源文件中实现。

正如文档所述,cProfile 通常是要走的路,只是因为它主要是用 C 实现的,所以一切都更快。

顺便说一句,您可以通过校准来提高profile 的性能。关于如何做到这一点的详细信息是 available in the docsDeterministic Profiling 上的 Python 文档部分中有更多关于所有这些东西是如何/为什么是这样的细节。和 limitations .

长话短说

cProfile 快得多,因为顾名思义,它大部分是用 C 实现的。这与 profile 模块形成对比,后者必须处理所有 native Python 中的分析回调。无论您是从命令行调用分析器还是在脚本中手动调用,都不会影响两个模块之间的时间差。

关于python - cProfile 需要很长时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25325788/

相关文章:

python - 如何生成带有 ids 偏移量的 charuco 板

python - 为什么 tensorflow reshape 数组超出范围

python - 为什么 cProfile 只运行一次代码?

python - 无法在我的 Pycharm CE 中找到探查器选项

python - 将多元函数根的求根算法中的两个根之一括起来

python - matplotlib 子图的行标题

python - 如何提取两个标记之间的子字符串?

python - 如何让 cProfile 只打印重要的功能?

python - 无法弄清楚如何在程序内部调用 cProfile