第十六章:开发工具-profile和pstats:性能分析-运行性能分析工具

16.8 profile和pstats:性能分析
profile模块提供了一些API,可以用来收集和分析有关Python源代码消耗处理器资源的统计信息。

16.8.1 运行性能分析工具
profile模块中最基本的起点是run()。它以一个字符串语句为参数,并且会创建一个报告,指出在运行这个语句时执行不同代码所花费的时间。

import profile

def fib(n):
    # from literateprograms.org
    # http://bit.lyy/hloQ5m
    if n == 0:
        return 0
    elif n == 1:
        return 1
    else:
        return fib(n - 1) + fib(n - 2)


def fib_seq(n):
    seq = []
    if n > 0:
        seq.extend(fib_seq(n - 1))
    seq.append(fib(n))
    return seq


profile.run('print(fib_seq(20));print()')

这是一个递归版本的Fibonacci序列计算器,他对于展示profile模块尤其有用,因为这个程序的性能可以得到显著改善。标准报告格式会显示一个总结,然后给出所执行的各个函数的详细信息。
在这里插入图片描述
原始版本有57359个不同的函数调用,并且运行时间为0.127秒,实际上这里只要69个原始调用,这个事实说明这57359个调用中大部分都是递归调用。所用时间的详细信息按代码清单中的函数分解,显示了调用数,函数花费的总时间,每个调用花费的时间(tottime/ncalls),一个函数花费的累积时间,以及累积时间与基本调用之比。
并不奇怪,这里大部分时间都花费在反复调用fib()上。增加一个缓存修饰符可以减少递归调用数,这会对这个函数的性能产生显著影响。

import functools
import profile


@functools.lru_cache(maxsize=None)
def fib(n):
    # from literateprograms.org
    # http://bit.ly/hloQ5m
    if n == 0:
        return 0
    elif n == 1:
        return 1
    else:
        return fib(n - 1) + fib(n - 2)


def fib_seq(n):
    seq = []
    if n > 0:
        seq.extend(fib_seq(n - 1))
    seq.append(fib(n))
    return seq


if __name__ == '__main__':
    profile.run('print(fib_seq(20));print()')

通过记住各层的Fibonacci值,大多数调用都可以避免,并且将运行的调用减至89个,这只需要0.001秒。fib()的ncalls数显示出它完全没有递归。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值