哪些模块可用于python性能分析_基准和性能分析

在本章中,我们将学习基准测试和分析如何帮助解决性能问题。

假设我们已经编写了一个代码,并且它也给出了期望的结果,但是如果想要更快地运行此代码,因为需求已经发生了变化。 在这种情况下,需要找出代码的哪些部分正在减慢整个程序。 在这种情况下,基准测试和分析可能很有用。

基准测试是什么?

基准测试旨在通过与标准进行比较来评估某些事物。 然而,这里出现的问题是,什么是基准,以及为什么需要软件编程。 对代码进行基准测试意味着代码的执行速度以及瓶颈的位置。 基准测试的一个主要原因是它优化了代码。

基准是如何工作?

如果我们谈论基准测试的工作,需要首先将整个程序作为一个当前状态,然后可以将微基准结合起来,然后将程序分解成更小的程序。 找到程序中的瓶颈并优化它。 换句话说,我们可以把它理解为将大而难的问题分解为一系列较小和较容易的问题来优化它们。

Python模块进行基准测试

在Python中,我们有一个默认的基准测试模块,称为timeit。 在timeit模块的帮助下,我们可以在主程序中测量一小段Python代码的性能。

示例

在下面的Python脚本中,导入了timeit模块,它进一步测量执行两个函数所需的时间 - functionA和functionB -

import timeit

import time

def functionA():

print("Function A starts the execution:")

print("Function A completes the execution:")

def functionB():

print("Function B starts the execution")

print("Function B completes the execution")

start_time = timeit.default_timer()

functionA()

print(timeit.default_timer() - start_time)

start_time = timeit.default_timer()

functionB()

print(timeit.default_timer() - start_time)

运行上面的脚本之后,将得到两个函数的执行用时,如下所示。

Function A starts the execution:

Function A completes the execution:

0.0014599495514175942

Function B starts the execution

Function B completes the execution

0.0017024724827479076

使用装饰器函数编写计时器

在Python中,我们可以创建自己的计时器,它的行为就像timeit模块一样。 它可以在装饰器功能的帮助下完成。 以下是自定义计时器的示例 -

import random

import time

def timer_func(func):

"""

A timer decorator

"""

def function_timer(*args, **kwargs):

"""

A nested function for timing other functions

"""

start = time.time()

value = func(*args, **kwargs)

end = time.time()

runtime = end - start

msg = "{func} took {time} seconds to complete its execution."

print(msg.format(func = func.__name__,time = runtime))

return value

return function_timer

@timer_func

def Myfunction():

for x in range(5):

sleep_time = random.choice(range(1,3))

time.sleep(sleep_time)

if __name__ == '__main__':

Myfunction()

上面的python脚本有助于导入随机时间模块。 我们创建了timer_func()装饰器函数。 这里面有function_timer()函数。 现在,嵌套函数会在调用传入函数之前抓取时间。 然后它等待函数返回并抓取结束时间。 这样,我们可以最终使python脚本打印执行时间。 该脚本将生成如下所示的输出。

Myfunction took 8.000457763671875 seconds to complete its execution.

什么是性能分析?

有时程序员想要测量一些属性,如使用内存,时间复杂度或使用关于程序的特定指令来衡量程序的真实能力。 这种关于程序的测量称为分析。 分析使用动态程序分析来进行这种测量。

在随后的章节中,我们将学习用于分析的不同Python模块。

cProfile - 内置模块

cProfile是一个用于分析的Python内置模块。 该模块是一个具有合理开销的C扩展,适合分析长时间运行的程序。 运行后,它会记录所有的功能和执行时间。 这是非常强大的,但有时难以解释和操作。 在下面的例子中,我们在下面的代码中使用cProfile -

示例

def increment_global():

global x

x += 1

def taskofThread(lock):

for _ in range(50000):

lock.acquire()

increment_global()

lock.release()

def main():

global x

x = 0

lock = threading.Lock()

t1 = threading.Thread(target=taskofThread, args=(lock,))

t2 = threading.Thread(target= taskofThread, args=(lock,))

t1.start()

t2.start()

t1.join()

t2.join()

if __name__ == "__main__":

for i in range(5):

main()

print("x = {1} after Iteration {0}".format(i,x))

上面的代码保存在thread_increment.py文件中。 现在,在命令行上用cProfile执行代码如下 -

(base) D:\ProgramData>python -m cProfile thread_increment.py

x = 100000 after Iteration 0

x = 100000 after Iteration 1

x = 100000 after Iteration 2

x = 100000 after Iteration 3

x = 100000 after Iteration 4

3577 function calls (3522 primitive calls) in 1.688 seconds

Ordered by: standard name

ncalls tottime percall cumtime percall filename:lineno(function)

5 0.000 0.000 0.000 0.000 :103(release)

5 0.000 0.000 0.000 0.000 :143(__init__)

5 0.000 0.000 0.000 0.000 :147(__enter__)

… … … …

从上面的输出中可以清楚地看到,cProfile打印出所有被调用的3577个函数,每个函数花费的时间和调用的次数。 以下是我们在输出中获得的列 -

ncalls - 这是要调用的数字值。

tottime - 这是在给定函数中花费的总时间。

percall - 它指的是tottime除以ncalls的商。

cumtime - 这是在这个和所有子功能中累计的时间。 递归函数甚至是准确的。

percall - 它是cumtime除以原始调用的商。

filename:lineno(function) - 它基本上提供了每个函数的相应数据。

¥ 我要打赏

纠错/补充

收藏

加QQ群啦,易百教程官方技术学习群

注意:建议每个人选自己的技术方向加群,同一个QQ最多限加 3 个群。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值