16.3.2 性能分析
让代码管用,还可能让它比最初更好之后,也许该来让它更快了。然而,或许不该这样做。正如高德纳转述C. A. R. Hoare的话时指出的:在编程中,不成熟的优化是万恶之源。不论优化诀窍再巧妙,如果根本用不着,就不用关心了。如果程序的速度已经足够快,代码清晰、简单易懂的价值可能远远胜过细微的速度提升。毕竟几个月后就可能有速度更快的硬件面世。
但如果程序的速度达不到你的要求,必须优化,就必须首先对其进行性能分析。这是因为除非程序非常简单,否则很难猜到瓶颈在什么地方。如果不知道是什么让程序速度变缓,优化就可能南辕北辙。
标准库包含一个卓越的性能分析模块profile,还有一个速度更快C语言版本,名为cProfile。这个性能分析模块使用起来很简单,只需调用其方法run并提供一个字符串参数。
>>> import cProfile
>>> from my_math import product
>>> cProfile.run('product(1, 2)')
这将输出如下信息:各个函数和方法被调用多少次以及执行它们花费了多长时间。如果通过第二个参数向run提供一个文件名(如'my_math.profile'),分析结果将保存到这个文件中。然后,就可使用模块pstats来研究分析结果了。
>>> import pstats
>>> p = pstats.Stats('my_math.profile')
通过使用这个Stats对象,可以编程方式研究分析结果。有关这个API的详情,请参阅标准库文档。
提示 标准库还包含一个名为timeit的模块,提供了一种对小段Python代码的运行时间进行测试的简单方式。在进行详尽的性能分析方面,模块timeit的用处不大,但在只需确定一段代码花了多长时间才执行完毕时,这是一个很不错的工具。手工测量的结果通常不准确(除非你对这方面了如指掌),因此使用timeit通常是更好的选择。
如果你非常在乎程序的速度,可添加一个这样的单元测试:对程序进行性能分析并要求满足特定的要求(如程序执行时间超过1秒时,测试就将失败)。这做起来可能很有趣,但不推荐这样做,因为迷恋性能分析很可能让你忽略真正重要的事情,如清晰而易于理解的代码。如果程序的速度非常慢,你迟早会发现,因为测试将需要很久才能运行完毕。
领取专属 10元无门槛券
私享最新 技术干货