過早的優化是萬惡的根源

林宏信
·
·
IPFS
·
「過早的優化是萬惡的根源」,在不存在效能瓶頸時就做優化,結果適得其反。比起效能,應該以可讀性優先。

有次我要開發一個規劃時間的演算法,需要將時間切割成一個一個單位做計算,這時普通的作法會是用布林陣列來儲存每個時間點,然而我需要對時間做一些 AND、OR、NOT 的布林運算,由於我當時突發奇想,想說假如用 BigInt 來儲存效能和記憶體都會省下不少,意思是將一個整數視作一個布林陣列,每一個位元就代表一個時間單位,這樣相比用布林陣列,足足省下至少 8 倍的記憶體。我心裡覺得這真是太酷了,於是就一股腦開發基於 BigInt 的演算法。

BigInt 由於本來就不是陣列,不論是讀值、改值都相當因難。以讀取第 i 項的值為例,需要寫成:

// normal index
array[i];
​
// bigint index
const n = 0b10111000;
(n >> i) % 2; // ???

看起來不直觀、可讀性差、又容易出現差一錯誤。debug 時也相當難纏,直接把 BigInt 印出來,會得到一個巨大十進位整數(本來它就是 Big Int 嘛),需要額外呼叫方法將其以二進位顯示,後來我還將其封裝成一個類別,花了好大力氣寫 unit tests、各種 debug function,最後終於將演算法給實作出來了,花了整整兩週的時間(side project 嘛)。

正當我得意於自己的成果時,遭到現實衝擊——我們使用 React Native 來開發 Mobile App,而 BigInt 是新語法,React Native 還沒有支援。我耗費好幾個小時嘗試各種偏方,然而都不得好轉,最後在無耐之下只好將演算法用陣列重寫。原先以為會天崩地裂、再花上一週的時間,然而由於我有非常多的單元測試,我竟然只用一個下午就將整個演算法改寫完了,比我研究如何在 React Native 跑 BigInt 的時間還少,而改寫後程式的可讀性也提升了不少,那效能呢?由於這是個跑在 client 端的演算法,效能根本不重要,使用體驗毫無差別,省下那一點點記憶體也一點用都沒有。

「過早的優化是萬惡的根源」,在不存在效能瓶頸時就做優化,結果適得其反。比起效能,應該以可讀性優先。

此外,單元測試真的很重要。

Original posted on wancat.cc

CC BY-NC-ND 2.0 授权

喜欢我的作品吗?别忘了给予支持与赞赏,让我知道在创作的路上有你陪伴,一起延续这份热忱!