加快Python速度
这其实是两个问题,但它们非常相似,为了简单起见,我把它们放在一起了:
首先:对于一个已经建立的Python项目,有哪些不错的方法可以让它运行得更快,而不仅仅是通过代码优化?
其次:在从头开始用Python写程序时,有哪些好的方法可以大幅提升性能?
对于第一个问题,想象一下你接手了一个写得还不错的项目,但你发现通过重构或优化代码,性能提升不大。那在这种情况下,除了把它重写成C语言之类的,你会怎么做来加快它的速度呢?
19 个回答
通常我们要做的就是:先进行性能分析,找出最耗时的那一行代码,弄清楚它在做什么,然后修复它。如果你之前没有做过性能分析,可能会发现一些看起来没什么问题的代码背后,隐藏着一些复杂的循环或者字符串重复的情况。
在Python中,我发现导致性能下降的两个常见原因是字符串拼接和生成器。因为Python的字符串是不可变的,所以像这样做:
result = u""
for item in my_list:
result += unicode (item)
每次循环都会把整个字符串复制两次。这种情况已经被很多人讨论过,解决办法是使用 "".join
:
result = "".join (unicode (item) for item in my_list)
生成器也是一个问题。它们使用起来非常简单,可以大大简化某些任务,但如果使用不当,生成器的速度会比直接把元素添加到列表中并返回列表要慢得多。
最后,不要害怕用C语言重写一些部分! Python作为一种动态高级语言,速度上是无法和C语言相比的。如果有一个函数在Python中再也无法优化了,可以考虑把它提取到一个扩展模块中。
我最喜欢的做法是同时维护Python和C语言版本的模块。Python版本要尽量写得清晰明了——这样任何错误都容易诊断和修复。对这个模块进行测试。然后再写C语言版本,并进行测试。它的行为在所有情况下都应该和Python实现一致——如果有不同,就很容易找出哪个是错的并修正问题。
与其直接转向C语言,我建议你:
让你的代码更高效。用更少的执行次数做更多的事情:
- 换一个更快的算法。很多情况下,算法不需要特别复杂就能更快。
- 使用一些用C语言写的Python基本功能。有些操作会让解释器处理得更慢,而有些则不会,后者是更好的选择。
- 小心那些先构建一个大数据结构再使用它的代码。想想`range`和`xrange`的区别。一般来说,考虑程序的内存使用是很重要的。使用生成器有时可以把O(n)的内存使用降低到O(1)。
- Python通常不会自动优化代码。把不变的代码提到循环外面,尽量消除紧密循环中的重复计算。
- 如果某个操作很耗时,可以考虑提前计算或者记忆化。比如,正则表达式可以预编译。
- 需要处理大量数字吗?你可以看看`numpy`这个库。
- 很多Python程序运行慢是因为受限于磁盘读写或数据库访问。在等待数据到达时,确保有其他有意义的事情可以做,而不是一直在那儿等。可以考虑使用像`Twisted`这样的框架。
- 注意,很多重要的数据处理库都有C语言版本,比如XML、JSON等。它们通常比Python解释器快得多。
如果以上方法都无法解决你代码的性能问题,那就考虑重写成C语言吧。
关于“第二点:在用Python从头开始写程序时,有哪些好方法可以大幅提升性能?”
记住杰克逊优化规则:
- 规则1:别做。
- 规则2(仅限专家):别急着做。
还有库纳斯规则:
- “过早优化是万恶之源。”
更有用的规则可以在优化的一般规则中找到。
不要边写边优化。先把程序写对了,再考虑速度。优化一个错误的程序,结果还是错的。
记住80/20法则。
始终进行“优化前”和“优化后”的性能测试。否则,你就不知道自己是否找到了80%的问题。
使用合适的算法和数据结构。这条规则应该放在第一位。没有什么比算法和数据结构更重要。
总结
你无法避免“优化这个程序”的工作。这是工作的一部分。你必须为此做好计划,并认真对待,就像设计、编码和测试一样。