没事儿别优化!

事实上你应该优化,但要在正确的地方,有足够的理由。我待会儿再聊这个。

我最近和在 Badgerpunch Games 的几位朋友一起发布了一个小的以XNA为基础的游戏,而且通过论坛和Twitter与这个独立的游戏开发组织保持密切的联系。游戏开发者十分在意性能问题,而且这很必要。没有人想要一个运行不畅的游戏。因为这些对性能的担忧,出现了很多关于优化技巧的提示和论文,都围绕着如何能实际有效的缓解性能问题。大多数的技巧提示和文章都提供了有价值的信息、有相应的用处,但你会发现很少有文章能触碰到性能优化上的主要问题:什么时候不该优化,为什么。

优化就是这样的事:你的程序可以一直优化下去,但工时上的开销和取得的效果的对比会很快让你陷入困境。我记起了九十年代早期在 Amiga Demo 公司的一幕。我大概花了半年的时间去优化那个3D旋转的汇编程序片段。最终我觉得该优化的几乎都优化了。起初几周我努力减少CPU的指令循环,获得了惊人的减幅!但随后的数月里,我几乎没法再进一步的压缩,最终只得放弃 … 我这段程序超级的快,可是,其他程序员的3D图形跑的比我还要快,我无法理解,这怎么可能?

直到数年后我在大学里学了矩阵后我才明白其中的奥秘。我的程序里每个3D坐标用9次乘法,这是一个没有优化的矩阵算法,它可以被压缩成6次乘和两个加法,这样每个坐标点可以节省数百次的CPU指令循环 … 太郁闷了!

这个故事的寓意?你可以优化你的程序,让它像星星一样闪亮,但如果有人有更好的算法,让同样的程序跑的更快,你还是很失败。

你很失败吗?只是在有意义的时候才能这样说。在上面的性能优化的故事里,3D旋转效果是被限制在一个16位的机器上的,这种情况下最快的程序证明了最出色的程序员,这时它的意义就很大了。 😉

这让我们回到了最初的那个问题。不要优化 —— 如果优化是无关紧要的。重要的是让你的代码简单易懂,容易修改!当你的程序具有这三个特征时,它是否被优化已经无关紧要了。

如果程序太慢,使用一个分析工具,找到什么地方需要优化。有时你并不需要一个分析工具,你只需要根据你的实际数据进行优化。当你找到了问题的区域,尽可能的用最简单的方式修改它们,看看修改后有什么效果。最终让你的程序达到到可以接受的性能程度。如果还不行,你需要根据你的代码做算法上的修改。这就是为什么要保持代码简洁、易于修改的原因了。

让代码保持简单易读、易于修改的主要原因是为了寻找bug,这是一个阅读和修改代码的过程。程序越易懂,问题越容易修改。这是毫无疑问的 … 可是仍然有人坚持把事情能的尽可能的复杂,只是为了满足个人的野心!我曾经看到一段Java代码里有多层递归调用的if语言。这是一个最糟糕的无意识里做出的损毁程序的事。必然的,到处都是bug … 看的我想哭。

另外一个保持代码简洁的原因是以最简单的方式告诉编译你的程序的意图。编译器对简单的代码有更好的优化能力。如果你是一个虚拟机上使用JIT编译器,这更显的重要。虚拟机和按需编译可以使你的程序能在不同的VM版本上运行。基本上虚拟机版本越新,你的代码越简单,当程序运行时,你就能获得更好的优化结果。

早期版本的Java虚拟机做很少的编译优化,所以像For循环反向计数等技巧可以节省一些循环。但是最新版的编译器和按需优化处理针对最常见的for循环形式进行了优化。性能问题从代码转移到了虚拟机上,长时间的运行的程序在代码上的优化技巧不再具有很重的份量。

所有的论述浓缩成这个:除非你知道优化什么,否则别去优化。这并不是说你不需要去考虑性能问题。你始终应该把性能问题放在心上。它有可能是你算法选择上的问题,设计、实现上的问题,但你的主要精力应该放在保持代码简洁易读,易于修改上。

[英文原文:Don’t optimize! ]
分享这篇文章:

3 Responses to 没事儿别优化!

  1. 道出了软件工程的精髓.

  2. ccxw1983 says:

    这告诉我们如何做有意义的事情。

  3. sebastian.wade says:

    I agree that optimizing often makes code more complicated. That is why I am advocating keeping the code as simple and clean as possible, and then optimizing where it matters.

发表评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据