最近遇到一些實際發生的例子,讓我深刻的體驗到,在程式設計者的這個行業裡,成本觀念似乎有愈來愈薄弱的趨勢。此處所指的成本觀念,並不是指總共花多少時間成本或多少人力成本來撰寫程式,而是指對於自己的程式在執行的時候,總共會耗去多少資源,在進行設計甚至到撰寫程式的同時,並沒有預先進行估計。也就是說,對於日後自己的程式在實際的環境中執行時,究竟會付出多少資源上的代價,其實不僅是毫無概念,甚至是毫不在意。

此處所指的成本,像是CPU在運算時會耗費的時間、存取檔案系統、資料庫系統時所會耗費的時間、佔用的網路頻寬、透過網路傳輸的資料量、取得資料需要的時間、……等等。

寫程式要考量會面臨的效能問題
前一陣子有一個實例大概是這樣子的。某一段程式碼,需要從某個伺服器讀取資料後,進行運算。在讀取資料的同時,會需要進行某種程度的鎖定,以確保所讀取資料的不可分割性。當程式部署到測試環境時,完全沒有察覺出來有任何的問題,但是,當程式正式上線,部署到正式的應用環境時,出了天大的災難,把整個系統的效能整個搞爛了。

究竟出了什麼問題呢?

因為這個系統有一個集中的資料伺服器,但是應用程式卻可能從世界各地連回集中的資料伺服器讀取資料,而位在世界各地的應用程式所在地,和資料伺服器所在地之間的網路連線速度有快有慢,偏偏就有幾個地方特別慢。

當這段程式碼在連線速度特別慢的地方,執行從資料伺服器讀取大量資料的動作時,由於讀取資料會造成鎖定,同時間自然不允許其他程式碼讀取資料,也由於讀取速度慢,那麼造成鎖定的時間也就拉長,排除其他程式讀取、造成其他程式必須等待鎖定解除的時間也就跟著變長。一堆程式頻繁地等著讀取的機會,自然造成系統效能低落。

既然也執行了測試的動作,為什麼在測試階段沒有找出這問題呢?

這邊當然是測試的程序也存在毛病。一來,在測試的方法中,沒有製造出有如正式應用環境中,向資料伺服器進行讀取時速度可能過慢的情況。二來,在測試的環境中,也沒有製造出規模可比擬正式應用環境中的大量資料。因此,當兩個主要的因素加在一起,造成了在測試的過程中,完全沒有人察覺到程式可能會隱藏這一個效能的大炸彈,結果,非得等到上線到正式環境後,才讓炸彈引爆,但也造成了傷害。

好吧,在這個案例中,測試的確有改善的空間。不過這不是本文的重點。除此之外,我觀察到,撰寫這段程式的程式設計者,可能在撰寫程式的時候,壓根沒有意識到自己這麼寫可能會存在極大的效能問題。

而為什麼沒有意識到呢?也很有可能是因為在撰寫程式的時候,很多人心裡根本沒有程式會耗費多少成本的概念。

程式要能執行,但也不能慢到令人無法接受
當然,這是個程式scalability的問題。程式本身是正確的,給定既定的輸入後,它也的確輸出了正確的結果──只是耗費較多的資源罷了。當程式所操作資料規模小時,表面上看起來沒有什麼異樣,但是當資料規模變得很大時,所耗費的資源量就會到達一個無法被接受的程度。

程式的scalability的問題,我想可以分為兩種。第一種是明白知道自己要克服scalability的問題,但是經過努力後,在技術上仍未能解決。而第二種則是,絲毫沒有意識到自己可能會遭遇到scalability的問題,然後直接寫下了無法scale up的程式碼。沒有意識到自己可能會遭遇到scalability的問題,就是一種成本觀念薄弱的象徵。

當你在撰寫程式的時候,也許該好好思考:

即將要處理的資料究竟會有多大規模?你的演算法究竟時間複雜度有多少?資料的傳輸究竟會耗去多少頻寬?程式執行所在的CPU速度有多快?網路連接存取的速度又有多少?

若不這麼做,你或許可以說是一個成本觀念薄弱的程式設計者。

這已經不是一個技術層面的問題了,這無疑是個心理層面的問題。當你完全不去設想,究竟執行你所設計的程式究竟要付出多少代價時,又怎麼能夠期待你的程式不會有scalability的問題呢?我想這單純只能靠運氣吧。

為什麼大家越來越不重視程式的效能?
那麼,為什麼在程式設計者圈子裡成本觀念似乎有愈來愈薄弱的趨勢呢?我有幾個猜測。首先,因為運算資源愈來愈充足了。CPU愈來愈快、網路頻寬愈來愈大、硬碟容量更是誇張,大到幾乎像是用不完一樣。那個斤斤計較不同指令花費的CPU時間不同、盡可能地壓縮資料使用量的時代已經過去了。計算資源充沛的程度,讓程式設計者,不必太花心思在資源的妥善運用,而且,也不會因此而讓scalability的問題造成困擾。

在很多的應用下,程式設計者不用去計較系統的架構是否足夠高效、演算法的複雜度是不是夠低、I/O存取的量和頻率是否可能成為效能的瓶頸、…。充沛的計算資源,讓這些議題彷彿變得不那麼的重要,因為就算不考慮它們,程式依然執行的夠快。這是,這些和效能相關的因素,有愈來愈不受重視趨勢的部份原因。

此外,高階程式庫、應用程式框架的普遍及流行,大幅的縮短應用程式開發的時間、提升開發生產力。但是,高階的抽象化包裝,同時也將程式設計者隔離在許多底層的細節之外。這是程式庫和應用程式框架的目標,甚至可以說,包裝的愈抽象的程式庫及應用程式框架,就是愈好的程式庫及應用程式框架。而效能問題,通常會在程式庫及應用程式框架這個層次上解決大多數。

但這不代表程式設計者沒有責任,因為程式設計者起碼需要在高階架構的層次上,去處理效能的議題。但是,過多的隔離和包裝,似乎讓不少程式設計者忘卻了,自己必須真正去處理效能議題,也忘了思考程式碼執行各種動作時,究竟會需要付出多少資源的成本及代價。

或許還有別的因素造成了撰寫程式時的成本觀念薄弱。但無論如何,對程式設計者而言,成本觀念薄弱最終還是會帶來傷害,即使大多數時候問題不會浮現,好比在本文中所舉的例子一樣。

看待程式開發過程中該採取的策略,要加上成本概念
程式設計者要具備成本觀念,才能成為一名優秀的程式設計者。有了這樣的觀念,在從事設計時,你會知道應該要先估算所面臨的問題規模、各種資源的配置情況,接著才能進行相對應的設計,以便在所處理的問題規模、有限的資源下,達到解決問題的目標。當你在撰寫程式碼時,同樣也會隨時準備要評估各種動作所花費的各種成本究竟有多少,來決定你撰寫程式碼的方式。

當然,有成本觀念的程式設計者,也不會做無所謂的效能最佳化,因為資源足夠的情況下,無所謂的效能最佳化,通常也只是浪費設計及開發的時間,所換來的效能提升可能一點都不重要,或微乎其微。

培養習慣,總是思考做每件事的成本代價,你的程式才不會在不知不覺中付出龐大的支出。

作者簡介


Advertisement

更多 iThome相關內容