沒事兒別優化!

aqee發表於2013-01-31

  事實上你應該優化,但要在正確的地方,有足夠的理由。我待會兒再聊這個。

  我最近和在 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!

相關文章