不知不覺,一月份就已經過去了。想想似乎這一個月,并沒有做什么事情。
這一個月,讀了幾本書。
通讀了一遍《Programming Scala》。因為Scala就是基于Java的,所以還算比較順利。不過,就在我寫這篇總結的時候,回頭翻看這本書的目錄,發現好多內容都沒有印象了。當時也沒有做筆記。幸運的是,畢竟只是一門編程語言,二月份開始,要用Scala寫Spark,可以鞏固一下對Scala的理解。
通讀了一遍《Programming Hive》。但是發現書中主要介紹的就是跟SQL相關的部分,只有自定義函數部分比較新鮮,于是就沒有仔細閱讀了,只是大體看了一下這部分,留下了一個印象,日后用的時候,能夠知道參考哪部分資料。
閱讀了《Kafka: The Definitive Guide》。這個月,由于家里有事情,回家了一個星期。這一個星期,忙完了之后,沒有什么事情可以做,就開始了這本書的閱讀。這本書,主要是精讀了前半部分,后半部分關于性能調優,部署等的內容就沒有細看。
目前為止,看過三本The Definitive Guide系列的書,《Hadoop: The Definitive Guide》,《HBase: The Definitive Guide》以及這本《Kafka: The Definitive Guide》。這個系列的書確實挺不錯,從一些基礎的內容,比如客戶端的使用,到一些比較深入的內容都有介紹。書中都會介紹這個項目的架構,如何進行優化等方面的內容。
項目的架構,有論文的參考論文,可以理解的更加透徹。而優化方面的內容,實際上并不是很詳細,只能說給一個大體的方向,具體的優化方法,還得根據實際的應用場景進行選擇。
除了技術方面的書籍,還閱讀一些其他方面的書籍。
先是閱讀完了《史蒂夫喬布斯傳》,從書中可以了解到Apple公司的興衰。書中的視角還算比較公正,對喬布斯的缺陷,沒有偏袒。
后來打算培養一下自己的藝術氣息,就讀了一部分《藝術的故事》。后來發現,似乎對藝術的感覺并不是那么強烈。
于是就閱讀其他的書籍,開始閱讀《未來簡史》,閱讀了三分之一左右,確實是蠻不錯的書籍,能夠引發對人類的本質的思考。
后來,在搜索書籍的時候,偶然發現了一本叫做《編程大師訪談錄》的書籍,目前正在讀這本書。這本書以對話的方式,記錄了一些大牛對編程的思索,以及其編程的習慣方式等。這本書的出版時間比較早,所以書中很多大牛的預測,在今天早已經實現了。這本書目前也讀了三分之一。從書中可以看到,所有大牛在當時都預測個人計算機將會非常普及。在當時大型機當道,出現的少量小型機也只有程序員這一個用戶群體,這樣一個時代,他們就有如此先見。今天,我們驗證了他們的預言。
在讀完這本書之后,再接著閱讀《未來簡史》。不過我估計二月份能夠讀完這兩本書就不錯了,因為時間不太多。
除了閱讀了一些書籍,還閱讀了一篇論文,《Bigtable: A distributed storage system for structured data》。由于之前已經通過《HBase: The Definitive Guide》這本書有了一個大體的了解,所以,閱讀起來還算是比較輕松。閱讀完論文就可以發現,HBase是嚴格按照這個論文來實現的。
除此之外,還閱讀了Hadoop中關于MapReduce以及YARN的源碼。對一個Job是如何Run,ResourceManager以及NodeManager是如何處理的,有了一個比較清晰的認識。但是,由于閱讀的時間其實并不長,當前只是注重于處理的流程,對一些比較重要的內容并沒有深入了解。比如:
- YARN中,幾種Scheduler的實現
- YARN中,幾種實現Container的方式
- MapReduce中,Reducer階段的幾種merger的實現
- YARN在啟動Container的時候,如何按照數據的存儲位置來決定Container的位置,從而減少數據的傳輸
- ApplicationMaster如何確定接下來要運行MapTask還是ReduceTask
這一個月,我也一直在探索,如何去獲取業界,以及學術界最新的進展。因為,之前看阿里的技術直播時,在介紹阿里內部實現的一個負載均衡器SLB(好像是這個名字)的時候,主講人介紹說,由于是在TCP/IP協議棧的第四層進行的負載均衡,以及用到了很多硬件方面的新進展,所以,基本上這個負載均衡器的性能就是硬件的性能。具體是那些進展,我現在也記不起來了。只記得當時在看的時候,就非常苦惱,為什么我就沒有地方獲取這種最新的進展呢?
仔細想想,猛然發現,其實,我學習的東西,看到的東西,都已經是非常老,非常穩定的了。即使也會嘗試一些業界出現的新技術,但是并不是這種底層的東西。不是底層的新的東西。而底層的進化,對于性能優化,有很大的幫助。
于是,我就一直在思索,也在探索,如何獲取業界和學術界的最新的進展。
想到之前在哪看到過,某某算法,或者某某技術,它們的論文,是最先發表在IEEE,或者ACM上面的。于是,就想著,或許可以從這里入手。也去IEEE或者ACM的Transactions或者Journal上,查看最新的論文集,來獲取學術界最新的進展。
后來,咨詢老師,也獲取到了另外一種途徑。就是查看對應領域都有某些頂級會議,然后通過查看這些會議收錄的論文集,來獲取最新的進展。
遺憾的是,雖然找到了獲取最新進展的方法,但是,由于目前是處于工業界中,并沒有太多的時間,讓我來仔細閱讀這些論文。
而且,很多領域,似乎并沒有頂級會議。我搜索了大數據方面以及分布式系統方面的頂級會議,但是,沒有搜索到。而關于數據挖掘,人工智能的倒是很多。不過幸好IEEE中都有對應的Transactions.
閱讀了上面的那些社科類,傳記類的書籍之后,我也意識到,社交圈子對一個人的影響真的很大。
美國著名物理學家費曼先生,在大學以及研究生的期間,其導師也是當時世界著名的物理學家。
比爾蓋茨雖然是中途輟學,但是,他就讀的是,哈佛大學,他的父親是國會議員,母親是IBM董事會成員。所以他有機會跟IBM合作,結識各種優秀的人。
我羨慕甚至嫉妒那些在Standford,麻省理工大學等有著世界上著名CS專業,有著世界上最優秀的科學家,有著世界上最優秀的導師,在這些大學的學生。
這些學生,也走在了相關領域的最前沿。
我羨慕他們,因為他們可以少走很多彎路。他們可以獲取到最新的知識,最權威的知識。他們可以學習到世界頂級科學家的工作方式,學習到很多我所學不到的東西。而我,自認為已經非常努力了,每天有效率地工作和學習接近十三個小時,卻也只能在世界的CS學生中,處于中等位置。
我自認如果我也能獲取到這些資源,必然不會比他們差,甚至會比他們更好。
但是我沒有這些資源。所以我經常會提醒自己,你只是一個渣渣,你完全可以做的更好。
在閱讀Hadoop的源碼的時候,從網上看到的關于優化Hadoop的方法,我就在想,為什么要這么優化?他們怎么知道要這么優化的?我從哪里也可以學習到這些關于優化的方法?
就在今晚,我突然有點想明白了。
性能調優的目的,就是為了提高性能。
那么我們怎樣提高性能?
- 讓程序使用更少的內存
- 減少寫磁盤的次數,或者往磁盤寫的字節數,因為磁盤的速度跟內存的速度差了兩個數量級
- 減少上下文切換的次數,以及內核態和用戶態之間轉換的次數
- 減少程序的步驟。每一個步驟,都是對性能的消耗。所以,能夠用更少的步驟做出來,就盡量用更少的步驟
- 優化網絡傳輸,比如,調節緩沖區大小,減少傳輸的字節數,選用合適的協議,UDP協議性能比TCP要好,因為它不存在三次握手這些額外的開銷,但是它需要忍受一些包丟失的狀況
- 阻塞和非阻塞
我認為,性能調優可以從三個方面進行:
- 針對業務進行調優
- 針對代碼進行調優
- 針對操作系統,內核等調優
第一條,針對業務進行調優。之前在一個群里,討論開源軟件的問題。有一位朋友就說,開源軟件,性能都很差,跟大公司內部實現的,性能方面根本沒有可比性。
我認為這種說法其實是不正確的。我不知道他是如何得出性能方面沒有可以性這一個結論的。但是,一款軟件,不管是開源的還是大公司內部的,假設我們只是拿過來使用,而不清楚它到底是為了什么而設計的,適應于哪些應用場景。你應該如何調節它讓它適應你的場景的話,那它的性能應該都不會達到最好的狀態。在大數據的處理過程中,假設我們不考慮數據傾斜的情況,而只是瞎分區,那么,數據處理的效率必然不高,木桶效應嘛。在MapReduce中,Mapper會將結果進行排序,然后輸出。假設我們有20MB的輸出數據,而緩沖區只有10M,那必然就會導致往磁盤讀寫數據,性能必然會有損失。
所以,在使用一款開源軟件的時候,我們至少應當先根據我們的業務場景,對它做一些調整。大公司內部實現的工具,未必就比這些好,只是他們充分考慮到了他們的需求,他們的業務場景,進行了針對性設計。而開源軟件則是針對大眾需求的。所以開源軟件的性能,可能看起來比不上大公司內部的軟件。
第二條,針對代碼進行調優。就拿JVM舉例,我們都知道,一般情況下,對象都是分配在堆內存上。一個對象在分配時,可能會導致Minor GC, Major GC。而且,一個對象在創建時,并不是簡單的在堆內存上分配內存就可以了,還要對對象進行初始化。所以我們如果可以重用一個對象,而不是每次都重新new一個對象,既可以避免可能產生的GC,又能不必重新初始化,效率必然高一些。所以,現在有很多重用的技術,比如,數據庫連接池,對象池,線程池,還有JVM復用等。在MapReduce中,JVM復用對于性能優化,有著不一樣的意義。因為JVM的創建相對來說還是比較重量級的,而每個Container啟動時都要創建一個JVM。另外,Hadoop中,也會根據數據所在的位置等信息,為Task分配Container,這樣就能減少很多不必要的數據傳輸。這些都是在代碼層面的優化。
代碼層面的優化還有很多,比如,在閱讀《Kafka: The Definitive Guide》時,作者提到了他們利用zero-copy來提高性能。zero-copy減少了數據傳輸的時候,用戶態和內核態切換的次數,復制的次數更少,因此,能夠提高性能。還有我們知道,NIO能夠減少線程的使用,既然線程的使用少了,需要進行互斥,同步的可能性就小了,我們使用鎖的幾率就小了。而且,上下文切換的次數就少了。性能自然高一些。很多其他的小細節,對于性能,都有一些或多或少的影響。
第三條,針對操作系統,內核進行調優。比如,調整操作系統交換區的大小,盡量避免換頁操作等,調節緩沖區的大小等。
如果能從這三個方面進行優化,我想,在使用這款開源軟件的過程中,應該不會有什么性能問題。
就算開源軟件有的地方在設計的時候確實不符合我們的業務,我們也是可以修改的嘛。
我們可以看到,這些優化的地方,其實都是跟操作系統密切相關的。我們必須理解操作系統的工作原理,如何讀寫數據,如何進行運算等,在優化的時候,才有理可依。
第三條那里,我寫的很少。因為我也不清楚,針對操作系統,針對內核,針對硬件,如何進行優化。實際上,目前,我之前最多只是在代碼層面進行過優化。對Linux操作系統,內核方面,硬件方面,不是很熟悉,自然也就沒有機會進行優化。
而且,上面說的那些優化的點,在進行Web開發的時候,可能并沒有什么。但是,如果我們要開發一款中間件,一款作為基石的產品,就必須要考慮這些因素了。
根據各種性能測試工具,發現性能瓶頸,進行針對性優化。
一月份總結完了,那么二月份,除了正常的工作,我要做什么呢?
- 深入閱讀MapReduce和YARN的源碼,理解上面我提到的幾個方面
- 挖掘MapReduce和YARN可以進行性能優化的地方
- 修改Hadoop的源碼,目前想到的有:
- 在Reducer階段,可以根據Value進行排序
- 讓Hadoop可以輸入不同Job的結果到相同的目錄,即如果Job的輸出目錄已經存在的話,也可以輸出,并不會報錯
- 總結MapReduce和YARN的源碼,并寫成文章發表出來
- 對Hadoop進行性能測試
- 閱讀《Linux Performance and Tuning Guidelines》,加深對Linux的理解,增強對Linux進行性能調優的能力
- 閱讀完《編程大師訪談錄》