在本章中,我们将了解基准测试和分析如何帮助解决性能问题。
假设我们编写了一段代码,它也给出了所需的结果,但是如果我们想更快地运行这段代码,因为需求已经改变,该怎么办。在这种情况下,我们需要找出代码的哪些部分会减慢整个程序的速度。在这种情况下,基准测试和分析可能很有用。
什么是基准测试?
基准测试旨在通过与标准进行比较来评估某物。然而,这里出现的问题是,基准测试是什么,为什么在软件编程的情况下我们需要它。对代码进行基准测试意味着代码的执行速度以及瓶颈所在。基准测试的一个主要原因是它优化了代码。
基准测试如何运作?
如果我们谈论基准测试的工作原理,我们需要首先将整个程序作为一个当前状态进行基准测试,然后我们可以结合微基准测试,然后将程序分解为更小的程序。为了找到我们程序中的瓶颈并对其进行优化。换句话说,我们可以将其理解为将大而难的问题分解成一系列更小、更容易的问题来优化它们。
用于基准测试的 Python 模块
在 Python 中,我们有一个默认的基准测试模块,称为 timeit。在 timeit 模块的帮助下,我们可以测量主程序中少量 Python 代码的性能。
例在下面的 Python 脚本中,我们将导入 timeit 模块,该模块进一步测量执行两个函数(函数 A 和函数 B)所花费的时间
运行上述脚本后,我们将得到两个函数的执行时间,如下所示。
输出
Function A completes the execution:
0.0014599495514175942
Function B starts the execution
Function B completes the execution
0.0017024724827479076
使用 decorator 函数编写我们自己的计时器
在 Python 中,我们可以创建自己的计时器,它的作用就像 timeit 模块一样。这可以在 decorator 函数的帮助下完成。以下是自定义计时器的示例 -
上面的 python 脚本有助于导入随机时间模块。我们已经创建了 timer_func() 装饰器函数。它里面有 function_timer() 函数。现在,嵌套函数将在调用传入的函数之前抓取时间。然后,它等待函数返回并获取结束时间。这样,我们终于可以让 python 脚本打印出执行时间了。该脚本将生成输出,如下所示。
输出
什么是性能剖析?
有时程序员想要测量一些属性,例如内存的使用、时间复杂度或有关程序的特定指令的使用情况,以衡量该程序的真实能力。这种对程序的测量称为 profiling。Profiling 使用动态程序分析来执行此类测量。
在后续部分中,我们将了解用于性能分析的不同 Python 模块。
cProfile – 内置模块
cProfile 是一个用于分析的 Python 内置模块。该模块是一个 C 扩展,具有合理的开销,使其适合分析长时间运行的程序。运行后,它会记录所有函数和执行时间。它非常强大,但有时有点难以解释和采取行动。在以下示例中,我们在下面的代码上使用 cProfile -
例
上面的代码保存在 thread_increment.py 文件中。现在,在命令行上使用 cProfile 执行代码,如下所示 -
从上面的输出中可以清楚地看出 cProfile 打印出所有调用的 3577 个函数,以及每个函数所花费的时间和调用它们的次数。以下是我们在 output 中获得的列 -
- ncalls − 它是拨打的电话数。
- tottime − 它是在给定函数中花费的总时间。
- percall − 它指的是 tottime 除以 ncalls 的商。
- cumtime − 它是在此子函数和所有子函数中花费的累积时间。它甚至对于递归函数也是准确的。
- percall − 它是 cumittime 除以原始调用的商。
- filename:lineno(function) − 它基本上提供了每个函数的相应数据。