我 相 信 這 么 優(yōu)秀 的 你
已 經(jīng) 置 頂了 我
文/王棟
轉(zhuǎn)自硅谷程序汪,已獲作者授權(quán),拒絕二次轉(zhuǎn)載
一周前,我面試了一個來自W Labs的Lead Big Data Engineer,問了他一個問題:在一維數(shù)組里找滿足條件的最長子數(shù)組,很不幸,這個Lead Engineer在45分鐘內(nèi)連暴力解法都沒有寫出來,于是在結(jié)束面試前五分鐘,我打住了他。
他和我說:現(xiàn)在大家都在處理大數(shù)據(jù),在Hadoop,Spark上跑程序,我們在這做算法題,優(yōu)化程序的目的是什么?
我當(dāng)時著急結(jié)束面試,草草回答他說:我只是測試你的編程基礎(chǔ)。
的確,從我13年開始工作到17年這四年,從內(nèi)存里讀1MB數(shù)據(jù)時間從15us降到6us;機器學(xué)習(xí)算法從跑在64核CPU變成了$8000的NVIDIA Tesla P100;Amazon服務(wù)器帶寬從50MB提升到了1GB。
硬件提升如此迅猛,而我們還要在面試的時候進(jìn)行白板測試,優(yōu)化算法,提升程序性能做什么?
程序的價值是什么?
有一天我和Uber的工程師??王聊代碼,他開篇就說,我加入Uber前沒見過那么屎的代碼,但就是這個代碼撐起了60B的共享經(jīng)濟帝國。
由此可見,程序的優(yōu)美性只是寫代碼要考慮的一個小問題,最重要的是代碼自身的價值。
很多時候優(yōu)化程序性能并不重要。如果你是一個Uber工程師,負(fù)責(zé)結(jié)賬功能的系統(tǒng)設(shè)計,因為每秒需要處理的請求并不多,所以要解決的問題的難度比微信紅包,支付寶要簡單不止一個數(shù)量級,在這種時候,考慮程序的性能可能是多此一舉。
著名的Pareto's Law,應(yīng)用到程序里面就是“20%的代碼占用了80%的運行時間”。這個現(xiàn)象在互聯(lián)網(wǎng)公司可能會更加極端-1%的代碼占據(jù)了99%的運行時間。
說到這,我們可以得出這樣一個結(jié)論:大部分的代碼都是不需要考慮性能優(yōu)化或者存儲優(yōu)化的。
但是!
對于剩下的那么一小部分代碼來說,優(yōu)化是非常重要的,好的工程師能看到優(yōu)化帶去的經(jīng)濟價值,而不是僅僅停留在優(yōu)化代碼的層面上。
好的優(yōu)化是可以量化的
人們認(rèn)識問題最直接的方式就是列數(shù)據(jù),分析經(jīng)濟價值。
從正面來看性能優(yōu)化是很值錢的,Apple網(wǎng)站上15寸的MacBook Pro有兩種型號,2.6G CPU要$2399,2.7G CPU要$2799。除去不到$150的硬盤差價,你需要花10%更多的價格來得到字面上不到4%的性能提升,而且這4%的性能還不一定能從日常使用中體現(xiàn)出來。
從反證的角度來看,如果程序性能不重要,我們用更快的電腦更短時間運行完程序并沒有額外價值。那么一個擁有16核的服務(wù)器應(yīng)該和一個擁有8核的服務(wù)器一樣貴,但實際上Amazon的c4.4x價格剛好是c4.2x價格的兩倍。
現(xiàn)在大家都在使用云服務(wù),每個月的收費是根據(jù)你的存儲空間使用和CPU消耗使用計算的,你的每一個優(yōu)化都可以被轉(zhuǎn)化成美金計算出來。Buffer就發(fā)表過一篇工程師文章《How We Saved $132k a Year With an IT Infrastructure Audit》談優(yōu)化節(jié)約了多少經(jīng)費。
另一種衡量方法就是去看用戶多喜歡你的產(chǎn)品。長久以來Microsoft的IE瀏覽器一直是市場霸主,但最近已經(jīng)被Google的Chrome瀏覽器后來居上了。在眾多人們喜歡用Chrome的原因里,排名第一的就是Chrome的啟動速度,網(wǎng)頁加載速度遠(yuǎn)勝于其他瀏覽器。
著名的獨角獸公司Pinterest也發(fā)過一篇Blog,談一系列hack的方法是如何將手機網(wǎng)頁加載效率提升了60%,與此同時帶來了40%手機網(wǎng)頁端用戶轉(zhuǎn)化率增長。
所以說,天下武功唯快不破。
加機器并不是優(yōu)化性能的良藥
有的不懂技術(shù)的人有這樣的認(rèn)識誤區(qū),我們可以用加機器,加內(nèi)存,加CPU這樣的方法加速程序,加大吞吐量。但哪怕Amadhl定律不約束并行程序效率,讓程序正確的運行在多核,多臺機器上也還是一個困難的問題。
投入更多的機器是一種提升性能的方法,但是既不便宜,也不簡單。
考慮這么兩種實際情況,一種是在單機上運行并行程序,最初我們可以從1 core變成3 core,將程序的性能提升一倍,但是如果你還想再提升一倍,那可能要16 core,因為程序不得不面對多核帶來的額外開銷,兼容性和調(diào)試的困難性。
另一種情況是常見的搜索引擎,當(dāng)我們使用5臺計算機來進(jìn)行搜索時,整個集群的P95耗時由單機的P99耗時決定,當(dāng)我們采用10臺計算機來搜索時,雖然每臺計算機處理的文檔減半了,但整個集群的P95耗時變成了單機的P99.5耗時,說不定latency就從100ms變成了200ms。
這樣看來,將單線程的代碼性能提高一倍在某些情況下意味著更大的經(jīng)濟價值,增加更多的硬件并不是提升性能的魔法,好的工程??才是。
那高級語言的性能怎么樣?
有人說,今天最流行的編程語言就是Python和Java了,但是他們的運行效率都比老牌語言C/C++差,這難道不是一個程序效率不重要的表現(xiàn)么?
我想要說,在你用著高級語言快速開發(fā)的時候,無數(shù)的程序員都在想著幫你優(yōu)化他們的運行效率。對于Python,有人研究Cython,有人研究Pypy,從底層優(yōu)化Python的程序效率;對于Java,越來越多的公司都在通過優(yōu)化它來優(yōu)化網(wǎng)頁速度,優(yōu)化用戶轉(zhuǎn)化率,很多新的框架都在強調(diào)效率提升。
在你使用高級語言,寫著更簡單,更安全的代碼時,你可能沒有看到,在最近的十五年來,Java在瀏覽器里的運行速度提升了兩個數(shù)量級,在Benchmarks Game的網(wǎng)站上,Node.js處理正則表達(dá)式之比C++慢3倍而已。
我們是不是也可以認(rèn)為這些年來Java變得越來越流行,一部分也是因為他的運行效率在不斷地提升。如果Java還和以前一樣慢,那估計現(xiàn)在沒有什么人會繼續(xù)使用了。
說到這里,我想向所有奮戰(zhàn)在internal tools的同事致敬,他們雖然很少實現(xiàn)面向用戶的功能,但是他們實現(xiàn)的功能幫助其他工程??節(jié)約了很多時間。
貪婪的程序員要求越來越高
還有一個讓人們忽視程序運行效率的因素就是著名的Moore定律,處理器和存儲讀寫會越來越快,誰還在意現(xiàn)在的程序效率呢?我們只需要用對的算法寫干凈的代碼就可以了。
在1990年的時候,人們想讓程序下國際象棋,那時候這是一個很困難的問題。你可能要在C++的代碼里加入一些匯編代碼進(jìn)行優(yōu)化,才能幫助計算機在短時間內(nèi)做出決策。但是今天,你可以直接用Python寫一個搜索程序來下國際象棋,并且戰(zhàn)勝大部分人。
電腦一天一天的在變快,人們的需求也在一天天的變大,十幾年前我們想讓計算機下國際象棋,下中國象棋,并且說下圍棋是很難解決的問題,因為圍棋的搜索空間太大。但是如今我們已經(jīng)可以用復(fù)雜的神經(jīng)網(wǎng)絡(luò)配上龐大的集群,打敗每一個圍棋大師。
同樣的道理也可以用在手機上,手機性能每一年都在提高,我們對手機的使用需求也隨著性能增加。讀初中,高中的時候我只在手機上玩黑白的貪吃蛇游戲,如今我們則玩著3d的戰(zhàn)略游戲,發(fā)送著語音命令...
可以想象,在不遠(yuǎn)的將來我們可能還會在手表上運行一些機器學(xué)習(xí)程序,幫助你做出一些決策,如果我們不優(yōu)化我們代碼的耗能,手機還能堅持12小時么?
優(yōu)化是讓處理器閑下來
最后一種說法,我們的處理器大部分時間處于空閑狀態(tài),即使程序慢,我們也可以讓CPU運行更長時間來彌補。
回?fù)暨@種想法只要打一個不恰當(dāng)?shù)谋确?,你會覺得買一個高級跑車但是長時間只放在車庫里很傻么?
在計劃你的網(wǎng)站需要多么大的集群支持時,都會為他準(zhǔn)備很多備用的計算資源,要是不這樣設(shè)計,運行程序就變成了去擁擠的超市里買菜,大家都在排著隊,從停車場到收銀臺,排一整天。
我們也都經(jīng)歷過電腦CPU占用率達(dá)到100%的狀態(tài),機器變熱而且任何程序都不響應(yīng),你只能無奈的等著。
如果搜索引擎的處理器在100%的狀態(tài)下運行著,那么新來的請求就會被放在隊列里,導(dǎo)致更多處理器切換造成了額外的消耗,最終服務(wù)器會徹底奔潰。
所以從設(shè)計的角度來看,我們需要我們的處理器處于空閑狀態(tài),有足夠多余的計算能力。
對程序的優(yōu)化就是讓處理器閑下來,更好的代碼幫助用戶更快的得到結(jié)果,并且消耗更少的資源。
結(jié)語
開了這么久腦洞,回到最初的面試。
我們有很多方法去衡量一個人,他是否對產(chǎn)品有準(zhǔn)確的理解,他是否有創(chuàng)造力,他是否理解用戶最需要的是什么。但如果單純衡量程序員,我們可以由簡單的兩點看起,他的程序是否運行正確,他的程序是否高效。
好的程序員能夠生產(chǎn)正確并且高效的代碼,這個定義看起來很簡單,但其實也是最難的。因為一旦你可以犧牲程序的正確性或者程序的效率,那很多問題都會變得更簡單,就好像CAP理論里一旦放棄一個要求,就有很好的實現(xiàn)方案。
所以,在下次面試的時候不要放棄優(yōu)化你的代碼。
在這里著重推薦一個我喜歡的blog,Daniel Lemire教授的《Does Software Performance Still Matter》,這是這篇文章整個骨干和靈感來源,我只是在里面加入了更多個人感受。
課外資料:
https://lemire.me/blog/2017/03/20/does-software-performance-still-matter/
https://benchmarksgame.alioth.debian.org/u64q/compare.php?lang=node&lang2=gpp
https://overflow.buffer.com/2016/03/31/how-we-saved-132k-a-year-by-spring-cleaning-our-back-end/
https://medium.com/@Pinterest_Engineering/driving-user-growth-with-performance-improvements-cfc50dafadd7
作者介紹
王棟
清華大學(xué)姚班07級,信息學(xué)競賽國際金牌。目前任職于硅谷電商網(wǎng)站W(wǎng)ish,專注搜索推薦算法及系統(tǒng)設(shè)計。曾任獨角獸公司Pinterest搜索排名負(fù)責(zé)人,帶領(lǐng)團隊設(shè)計和實現(xiàn)了高度可擴展的搜索平臺,以及機器學(xué)習(xí)搜索結(jié)果排名算法。
—————END—————
看完本文有意思?請分享給更多人
小伙伴們,你怎么看!
轉(zhuǎn)載請注明來自夕逆IT,本文標(biāo)題:《電腦存儲空間的kb、mb怎么念?兆是什么意思?》

還沒有評論,來說兩句吧...