過早的優化是萬惡的根源
有次我要開發一個規劃時間的演算法,需要將時間切割成一個一個單位做計算,這時普通的作法會是用布林陣列來儲存每個時間點,然而我需要對時間做一些 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
Like my work? Don't forget to support and clap, let me know that you are with me on the road of creation. Keep this enthusiasm together!
- Author
- More