python - 有没有简单的方法来对 Python 脚本进行基准测试?

标签 python unix shell benchmarking

通常我使用shell命令time。我的目的是测试数据是小、中、大还是非常大的集合,需要多少时间和内存。

任何适用于 Linux 或仅 Python 的工具可以做到这一点?

最佳答案

看看timeit , the python profilerpycallgraph .另请务必查看the comment below by nikicc 提到“SnakeViz”。它为您提供了另一种分析数据的可视化,这可能会有所帮助。

时间

def test():
    """Stupid test function"""
    lst = []
    for i in range(100):
        lst.append(i)

if __name__ == '__main__':
    import timeit
    print(timeit.timeit("test()", setup="from __main__ import test"))

    # For Python>=3.5 one can also write:
    print(timeit.timeit("test()", globals=locals()))

本质上,您可以将python代码作为字符串参数传递给它,它会在指定的次数内运行并打印执行时间。 docs 中的重要信息:

timeit.timeit(stmt='pass', setup='pass', timer=<default timer>, number=1000000, globals=None) Create a Timer instance with the given statement, setup code and timer function and run its timeit method with number executions. The optional globals argument specifies a namespace in which to execute the code.

...和:

Timer.timeit(number=1000000) Time number executions of the main statement. This executes the setup statement once, and then returns the time it takes to execute the main statement a number of times, measured in seconds as a float. The argument is the number of times through the loop, defaulting to one million. The main statement, the setup statement and the timer function to be used are passed to the constructor.

Note: By default, timeit temporarily turns off garbage collection during the timing. The advantage of this approach is that it makes independent timings more comparable. This disadvantage is that GC may be an important component of the performance of the function being measured. If so, GC can be re-enabled as the first statement in the setup string. For example:

timeit.Timer('for i in xrange(10): oct(i)', 'gc.enable()').timeit()

分析

分析将使您更详细地了解正在发生的事情。这是来自 the official docs 的“即时示例” :

import cProfile
import re
cProfile.run('re.compile("foo|bar")')

这会给你:

      197 function calls (192 primitive calls) in 0.002 seconds

Ordered by: standard name

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1    0.000    0.000    0.001    0.001 <string>:1(<module>)
     1    0.000    0.000    0.001    0.001 re.py:212(compile)
     1    0.000    0.000    0.001    0.001 re.py:268(_compile)
     1    0.000    0.000    0.000    0.000 sre_compile.py:172(_compile_charset)
     1    0.000    0.000    0.000    0.000 sre_compile.py:201(_optimize_charset)
     4    0.000    0.000    0.000    0.000 sre_compile.py:25(_identityfunction)
   3/1    0.000    0.000    0.000    0.000 sre_compile.py:33(_compile)

这两个模块都应该让您了解在哪里寻找瓶颈。

另外,要掌握 profile 的输出,看看this post

pycallgraph

注意 pycallgraph 已被正式废弃since Feb. 2018 .不过,截至 2020 年 12 月,它仍在使用 Python 3.6。只要 python 公开分析 API 的方式没有核心变化,它应该仍然是一个有用的工具。

This module使用 graphviz 创建如下调用图:

callgraph example

您可以通过颜色轻松查看哪些路径使用时间最长。您可以使用 pycallgraph API 或使用打包脚本创建它们:

pycallgraph graphviz -- ./mypythonscript.py

虽然开销相当大。因此,对于已经长时间运行的流程,创建图表可能需要一些时间。

关于python - 有没有简单的方法来对 Python 脚本进行基准测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1593019/

相关文章:

shell - 如何检查是否$?在 unix shell 脚本中不等于 0?

python - 想要隐藏 "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python3" } from ping module output?

linux - "cat/dev/random"与 "tail -f/dev/random"

制作或制作。我需要两者吗?

linux - 如何以编程方式查找 php.ini 文件的位置?

linux 按日期列分组并显示计数

python - 在 Python (Django) 中转换时区,添加神秘的 30 分钟

python - 编写交叉兼容的 Python 2/3 : Difference between __future__, 六和 future.utils?

python - 使用 POST 请求的谷歌反向图像搜索

shell - UNIX shell : sort a string by word length and by ASCII order ignoring case