Python 高手编程系列一百九十一:降低复杂度

在我们进一步深入学习优化技术之前,让我们准确地定义我们要处理的问题。从本章
的介绍中,我们知道专注于改善应用程序的瓶颈对于成功优化至关重要。瓶颈是严重限制
程序或计算机系统处理能力的单个组件。每个有性能问题的代码都有一个重要特点,就是
它通常只有一个瓶颈。我们在前一章讨论了一些分析技术,因此你应该已经熟悉定位和隔
离这些地方所需的工具。如果你的分析结果显示有几个地方需要立即改进,那么你应该首
先尝试将每个一个地方作为单独的组件,并且进行独立优化。
当然,如果没有明显的瓶颈,但是你的应用程序的运行情况仍然低于你的预期,那么
这你来说真的很不利。优化过程的收益与优化瓶颈的性能影响成正比。有些小组件对总体
执行时间或资源消耗没有实质性的影响,分析并优化这些小组件,需要花费大量的时间,
而收益却很小。如果你的应用程序似乎没有真正的瓶颈,有可能是你错过了一些东西。尝
试使用不同的分析策略或工具,或从不同的角度(内存、I/O 操作或网络吞吐量)查看它。
如果这仍然没有帮助,那你应该考虑调整你的软件架构。
但是,如果你已经成功地找到一个单一的整体组件,它限制了你的应用程序的性能,
那么你真的很幸运。很有可能只需要改进极少的代码,你将能够真正地改善代码的执行时
间并且(或者)资源使用。并且优化的增益将再次与瓶颈的大小成比例。
当尝试提高应用程序性能时,第一个也是最明显的方面就是复杂度。有很多关于程序
复杂性的定义以及很多的表达方式。一些复杂度指标可以提供代码行为的客观信息,并且sqc 这样的信息有时可以用来推测性能的预期。有经验的程序员甚至可以根据不同实现的
复杂性和实际的执行上下文,可靠地猜测它们在实践中的运行情况。
定义应用程序复杂度的两种常用的方式是:
• 循环复杂度(Cyclomatic complexity),往往与应用程序的性能相关。
• 朗道记法(Landau notation),也称为大 O 记法,在客观判断性能中,这是一种非常
有用的算法分类方法。
从那里开始,优化过程有时可以被理解为降低复杂度的过程。本节通过简化循环提供
了简单的技巧。但首先,让我们学习如何测量复杂度。
循环复杂度
循环复杂度是由 Thomas J. McCabe 在 1976 年提出的一个度量指标。由于的作者原因,
它经常被称为 McCabe 的复杂度。它通过代码测量线性路径的数量。所有的 if、for 和
while 循环都计算在一个度量中。
然后可以将代码按照表 12-1 的方式进行分类。
表 12-1
循环复杂度
含义
1~10
不复杂
11~20
中等复杂
21~50
真复杂
大于 50
太复杂
循环复杂度不是代码质量的得分,而是客观地判断其性能的度量指标。它不能取代代
码分析,代码分析在查找性能瓶颈的时很有必要。总之,具有高循环复杂度的代码通常倾
向于使用相当复杂的算法,当有大量输入时,这些代码就会表现的比较糟糕。
虽然循环复杂度不是一种判断应用程序性能的可靠方法,但它有一个非常好的优势。
它是一个源代码的指标,因此可以使用适当的工具进行测量。其他表达复杂度的方式—大
O 记法,不能这样测量。由于可测量性,循环复杂度可以作为对性能分析的有用补充,它
可以为你提供有关软件问题部分的更多信息。当考虑对代码架构进行重新设计时,应该首
先评审代码的复杂部分。
在 Python 中,测量 McCabe 的复杂度是相对简单的,因为它可以从它的抽象语法树中推
导出来。当然,你不需要亲自去做。已经在第 4 章中介绍过一个 Python 中常用的工具—
flake8(以及 mccabe 插件),它可以测量代码的循环复杂度。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值