英文原文:Simple and Clean Code vs. Performance
原文作者 Arne Mertz 是一位 C++ 狂热份子,有着丰富的开发经验。文中 Arne Mertz 针对简洁和性能的关系进行阐述,他认为,开发者不到万不得已时千万不要为了性能而牺牲简洁性,要学会使用工具来解决性能问题。
译文如下:
C++的强项之一是能写出非常高性能的代码。那么在实际中,我们该如何把握好性能处理的尺度呢?
性能≠效率
首先要明确的一点是我们必须把性能和效率区分清楚。这两者分别代表什么?
这看上去好像差不多,但其实不是。举个例子,假设你需要从A点到B点,效率意味着“最短路径”,性能意味着“以跑代走”。因此,即使以博尔特的速度到达终点,虽然高性能,但并不高效—“没有选择最短路径”。
对于程序来说,循环通常会耗费不少时间。这种情况下,性能意味着“单个循环用时越短越好”,效率意味着“尽量降低循环层数”。
性能并非程序的全部
这是很浅显的道理,但往往容易被忽视,特别是程序员新手。在不少编程论坛里,涉及代码性能优化的提问比比皆是。
有个说法是80% 的程序运行时间是由约 20% 代码决定的,还有的说是 90%/10%。因此,对于程序来说,关键运算代码可能仅存在于某小部分代码中。所以,如果把精力放在所有代码的优化上,而不重点主攻关键代码,其实是事倍功半的。
我们真的不懂如何写高性能的代码?
事实上,决定程序运行时长主要的因素是指令数的多少,但这不是由我们控制而是由编译器及其优化器所控制的。
优化器种类繁多,除非是该领域的专家,否则很难明白它对代码做了哪些优化工作。优化器可以销毁临时对象,可以内联函数,可以清除更多其它指令。
所以当这些不确定因素存在时,我们还能写出绝对高性能代码吗?如果真的很在意性能,我建议使用工具来辅助完成。
但也不必太悲观。如果有两种或更多的方法来写出同样可读的代码,那么不妨选择最高性能的写法。例如,在不存储结果的情况下,可以使用++iter 来代替 iter++。
性能和简单并不总是矛盾
影响程序运行时间的另一个重要因素是内存中数据的布局和结构。详细请参考 Chandler Carruth 的文章 Efficiency with Algorithms, Performance with Data Structures。
补充一点,假如数据的内存布局不优良,那么会造成要花费很多时间来从获取数据,同时会造成指令冗余。
对于简洁和性能的关系,还可以参考文章 Using the libraries you have, and using them right。
小结
建议默认编写出可读和简单的代码。如果你真的发现存在性能问题并已经找出其位置,那么仍然有很多选择来对此进行处理而不必为了追求快而写出复杂的代码。不到万不得已不要为了性能而牺牲简洁性,同时要学会使用工具来解决性能问题。