技術十年-迴歸自己十年技術經歷

高效能架構探索發表於2021-11-08

走過的路,回憶起來是那麼曲折,把自己的一些心得體會分享給程式設計師兄弟姐妹們,雖然時代在變化,但是很可能你也會走我已經走過的10年的路程,有些心得體會你可以借鑑一下。

在某一天的某一個時候,突然意識到,自己已經畢業工作十年了,是該寫篇東西,來記錄下自己的十年,算是給自己一個心理的慰藉,亦算是給自己入職場以來,第一個十年的總結。

大學生活

我是03年上的大學,上大學之前,完全沒有接觸過計算機。大學報志願也是懵懵懂懂,那個時候,最火的兩個專業,一是計算機,一是生物工程。電視上經常說的已經話就是:21世紀,是生物科學的世紀。而我呢,因為沒有摸過電腦,所以比較好奇,就在填報志願的時候,寫上了對於現在來說最內卷的一個行業專業:電腦科學與技術。

於是乎,在9月份的某一天,坐著穿越近半個中國的火車,來到了北方某個城市,開始了所謂的大學生活。現在還清楚的記得,第一次上機課,在機房開啟電腦,雙擊點開網路上的芳鄰,輸入網址,聽的第一首歌,就是劉若英的“很愛很愛你”,以至於很多年以後,每次聽到這首歌熟悉的旋律,都會回憶起自己大一的第一次上機課的情景。

那個時候,剛剛脫離了壓抑的高中生活,就像長了翅膀的鳥兒,自由自在的翱翔在空中,秉持著“六十分萬歲,多一分浪費”的學習心態,得過且過,基礎課和專業課都均分通過,也算是沒留丁點遺憾把。

就這樣,度過了大一的懵懂,大二的彷徨,大三的沉淪,直至大三下的時候,才開始考慮自己的未來,跟隨自己的內心,選擇了考研。

研究生生活

慕名來到了以學習刻苦出名的華東某校,開始了自己的內卷生活。吃了不少專業課的苦,也算是對自己本科期間的一個懲戒。每天的三點點一線生活,宿舍、食堂、圖書館,開始了自己專業技術的學習。買的第一步程式設計方面的書,就是c++ primer,在圖書館借閱了c++大學教程,開始學習程式設計,隨著對專業書籍的廣泛接觸,開始更加深入的去了解底層原理,c++模型深度探索,effective c++,more effective c++,c++沉思錄等等,好多書都是在那個時候開始接觸,也算是給自己後面進入本行業,打下了堅實的基礎。

實習生活

那個時候,對自己就業開始有了危機感,周圍的同學都拿到了阿里雲、訊飛等公司的實習offer。終於,自己在快要崩潰的時候,拿到了中科院某所的實習offer,記得同宿舍哥們的第一句話就是:恭喜你,多年的媳婦熬成婆。

來到了北京,住在了所裡安排的宿舍,跟著mentor做一個國家863專案,ddos攻擊相關的。因為是實習生,所以接觸的是一些優化類的,比如記憶體池等。

在所裡實習的同時,自己開始接觸csdn網站,除了專案,就是整天泡在c++版塊回答問題,當初的積分很高,排名也很不錯,不過因為其他原因,工作後,也不再登入該論壇了,算是一個不小的遺憾吧,在裡面還是能學到不少東西,猶記裡面有個技術很牛的群(音譯 餅子堂),自己有幸也加入了,後面還是退出了。

隨著所裡專案的終結,選擇去了另外一個大外企實習,該企業在西二旗(大家應該能猜出來是哪家吧),專案組是做一整套Linux下的辦公系統,類似於Windows下的word,基於openoffice來做的。整個專案百萬行,光編譯就得兩三個小時,自己在裡面負責解決記憶體洩漏,在此需要提的是,當時的mentor是個大牛,基本上整個公司的難題都會去找他,使得自己對技術的理解更加深入。

初入職場

進入傳統行業

第一家公司,是個傳統行業,有幸進入了公司技術最厲害的技術研究院,做網路相關的研發工作,也就是在這家公司,開始了研究TCP,把TCP/IP詳解看了一遍又一遍,不懂的就去查資料,甚至把原始碼下載下來進行分析研究。也是在這家公司,第一次接觸Linux系統。

由於公司的業務面向的是國企,主要執行在Windows系統,第一要求就是穩定,所以更新迭代很慢,有時候一個功能幾年都沒進行優化。後面隨著Linux系統在國內用的越來越多,部門的業務也需要執行在Linux系統上,當時有兩個選擇,一個是重新在Linux系統上寫一份程式碼,一個就是現有的程式碼可以完全移植到Linux系統,即同一份程式碼可以在Windows和Linux兩大系統,最終為了效率,還是選擇了第二種方案。

大家都知道,雖然c++是跨平臺的語言,但是API名稱,以及底層實現卻是依賴於系統的,就比如WaitForSingleObject函式,在Linux gcc下就是std::lock,這就要求同一個函式,比如WaitForSingleObject,在Windows下使用的系統自帶API,而在Linux下是重新開發的一個函式,其功能與Windows下類似。當初這塊是我來負責完成的,第一次出現了coredump,第一次使用gdb進行除錯。

入職網際網路

那幾年,正式網際網路行業開始火的時候,自己內心也蠢蠢欲動,於是幾經坎坷,進入了一家網際網路行業,也算是自己第一次接觸網際網路。

剛入職的時候,確實很不習慣裡面的快節奏,經常一個需求從提出到上線就幾天,這在之前的傳統行業是萬萬不可能的,第一次上線就導致線上服務coredump,飯吃一半就跑上去解決。。。,在這家公司學到很多,對業務越來越熟練,開始負責整個推薦引擎,為後面接觸廣告奠定了基礎。

接觸廣告

由於公司的業務發展遇到了瓶頸,再加上其他一些原因,又開始看機會。由於推薦引擎和廣告引擎無論在架構上還是功能上都很類似(index->filter->rank等等)。所以有幸進入了廣告行業。

在這家公司,對我的影響很大,如果說上一家公司給了我進入網際網路的機會,那麼在這家公司,我開始了思考,怎樣能讓服務效能更優,怎樣在系統設計上更加具有前瞻性,也算是逐步接觸架構,開始從架構去了解整個業務,又從業務去反推架構的合理性。

眾所周知,廣告對rt(Response Time)要求很高,rt每增加幾毫秒,廣告展示折算率就會變大,所以對於每天請求百億次的服務來說,對業務處理效能非常高,某一個子服務的效能都會影響整個廣告鏈路。比如:

  • 廣告候選集過大,導致處理時間變長
  • 某塊程式碼耗CPU過高
  • 傳輸鏈上無用引數過多
  • 其它

記憶比較深刻的,實現了一個DMP服務,因為效能原因,所有的操作都在記憶體裡面進行。裡面用到了大量的記憶體分配以及釋放,上線後,發現了一個現象,就是記憶體利用率一直很高。從表面現象看,就是記憶體沒有被釋放,即使程式顯示呼叫了delete或者clear,其記憶體佔用仍然居高不上。為了解決這個問題,用了各種記憶體檢測工具,加上了日誌(申請記憶體和釋放記憶體都加上),發現仍然沒有問題,於是就去調研底層庫,去研究記憶體分配的原理,通過研究原始碼,調研new和或者malloc的原因,最終發現,在底層API中,即使呼叫了delete或者free,記憶體都不會被立即釋放給作業系統,而是被放在緩衝區中(這就是記憶體佔用比較高的原因),等間隔一段時間,才會被作業系統回收,如果想立即被作業系統回收,需要malloc_trim(0)。

還是同一個DMP服務,由於其記憶體佔用過大,導致效能不是很高,大量的Misscache,最終,通過將系統中page大小從預設的4k變為32k,解決了這個問題(這是因為page過小的話,導致大量的缺頁中斷,具體可參考<深入理解作業系統>)。

程式設計能力

作為程式設計師,程式設計能力是我們的立身之本, 就我自己的感受而言,我覺得程式設計能力的成長主要有這麼幾個部分。

初級

初級程式設計能力,就是 會用。也就是說 使用各種系統API,能夠達到我們的目的就行。

程式設計,首先是從學習該門語言的語法開始的,比如if/else while等,作為初級程式設計師,建議在入門的時候,使用入門級別的書,而不是去看一些比較高階的書。(對於c++而言,<c++ primer>並不適合入門級的讀者去看,反而適合有一定c++基礎知識的人去閱讀,這本書的名字起的太具有誘惑性)。

除了看文件以外,程式設計是個超級實踐的活,所以一定要多寫程式碼,只有這樣才能真正熟練起來,有句話"無他,唯手熟爾",很適合入門級程式設計師。作為入門級程式設計師,儘量不要使用IDE,這種會使得對IDE具有依賴性,導致手寫很難,希望儘量做到所有的API名稱都能敲出來,久而久之,就會越來越熟練。

在初級階段,核心就是多寫,勤學苦練,這個很重要,只有這樣才能為以後奠定紮實基礎。

中級

初級的目標是能夠熟練使用程式語言實現功能,中級的的目標就是提升 分析和解決問題的能力

作為程式設計師,寫程式碼過程中出問題是非常正常的,而怎樣去有效且高效的排查問題,這是個體程式設計師之間程式設計能力上最大的差距,解決問題能力強,那麼很容易受到上級乃至其他部門同事的認可。

在查問題的能力上,首先要掌握的是一些基本的除錯技巧,好用的除錯工具,比如常用的gdb,gperf,btrace等。熟練掌握除錯工具,對解決問題非常有利。有些時候大家在查問題時的能力差距,有可能僅僅是因為別人比你多知道一個工具而已,除了除錯技巧和工具外,查問題的更高境界會和程式設計能力的高階階段有非常大的關係,就是懂原理,一個懂原理的程式設計師在查問題的水平上是有明顯差距的。多嘗試給自己寫一些會出問題的程式,多積極的看別人是怎麼查問題的,多積極的去參與排查問題,很多最後查問題能力強的人多數僅僅是因為“無他,但手熟爾”。

除了查問題外,更厲害的程式設計師是在寫程式碼的過程就會很好的去避免問題,他們會知道在這塊怎樣做才不會入坑,在這塊會出現怎樣的問題,需要加什麼樣的條件或者日誌等。

在中級階段,建議大家去主動分析和解決問題,成為一個能寫出高質量程式碼、有效排查問題的優秀程式設計師。

高階

對於高階程式設計能力的程式設計師來說,一個標準就是 懂的底層API的實現原理,知其然,知其所以然。

在學習底層實現以及排查問題的過程中,越來越明白懂程式語言的執行原理是非常重要的。學習底層實現最直接的去看原始碼,但這對很多人來說很難,所以可以嘗試著從文件或者一些書籍入手(<STL原始碼剖析>),一邊看書,一邊找到對應的原始碼去分析,這樣就能達到事半功倍的效果。

有人說過,語言只是一種工具,解決和分析問題,不要侷限於語言,我很同意這種說法。比如雖然c++效能很優,但是其實現過程比較麻煩,會出現很多坑。對於一些猛操快的需求,比如分析線上日誌,可以使用python或者shell去解決。

架構能力

隨著寫的程式碼越來越多,不經意間,在寫程式碼的時候,開始考慮效能上是否最優,架構上是否合理,是否能夠做到日後靈活擴充套件。

完全搭建一個系統,是在五年前,也就是工作五年的時候,那個時候入職了現在的公司。剛開始要做商業化,什麼都沒有,所有的都要從0開始搭建。比如一個流量來了,該如何去請求各個業務線,一個廣告訂單來了,如果能夠快速的進入廣告系統。那麼就需要合理的進行模組分配。

隨著程式碼寫的越來越多,解決問題越來越多,越來越難,設計的模組越來越多,在潛移默化中,架構能力也就有了,在設計一個系統的時候,就開始有前瞻性,考慮解耦,考慮擴充套件。

架構能力並不是一朝一些就能學會的,更多的需要從實踐中來,到實踐中去,久而久之,這種能力就會得到提升。

心得

團隊精神

在一個各項流程都完善的公司,需求評審、開發、測試、上線幾個流程缺一不可,缺少每一個環節都可能導致線上故障,所以一個需求的完成,是需要各個部門通力合作的。

線上有了問題,大家一起努力將其解決,這就是成長的過程。

不要炫技

程式碼,是需要傳承的。大家都不希望自己的程式碼被後面接手的人罵吧,所以程式碼一定要簡潔、清晰、明瞭。不要為了炫耀某些技術實力,而故意使用晦澀難懂的程式設計技巧,相信過不了多久,不止是別人,即使是本人,也有可能看不懂這塊程式碼。

合理架構

架構方案千千萬,選擇一個合適的最重要,不要為了架構而去架構,要考慮效率以及功能需求。

做到架構和開發效率雙平衡,再向後展望,看看現有架構設計能否滿足需求。

攻守兼備

所謂的攻,即進攻,也可以理解為攻城。即實現產品目標,滿足功能需求;所有的守,即守衛,也可以理解為守城。即對於線上問題,能夠守衛,快速解決。

正所謂攻城容易,守城難。線上bug永遠解決不完,需要有耐心,需要有攻守兼備的能力。

程式碼審查

codereview是必不可少的,這需要團隊精神,可以在上線前期,解決不少問題。

但是也有弊端,這就是可能會導致大家有矛盾,比如有個功能實現,A說這樣實現,B說那樣效能更好,久而久之,就會導致團隊之間出現矛盾。這就需要找一個平衡點,對於可有可無的意見,可以不提。。。

程式碼註釋

程式碼是最好的註釋。 這是終極目標,但很多人達不到,當然也包括我。所以程式碼中要儘可能多的註釋,原因:

  • 為了自己以後維護
  • 方便他人接手

尤其是對於功能複雜的函式,可以用1、2、3等點寫出來,必要的時候,寫在cf上,函式註釋處加上url連結。

程式碼結構

程式碼結構一定要清晰,簡潔明瞭,通過看函式說明就知道其功能,通過類名就能其要做什麼。

程式碼結構表現出來的其實是程式的一個模組邏輯思想。結構簡單清晰,也就能說明程式實現邏輯簡單。

程式碼風格

程式設計師都是團隊協作的,每個人都有自己不同的程式設計風格,如果沒有一個統一的風格,整個程式碼將會很亂。

現在業界都用的谷歌程式碼規範,同樣推薦給大家。

開發效率

c++程式設計師有個特點,就是不喜歡用IDE,也算是他們的一種特有的驕傲吧,喜歡用vim(我就是),所有的程式碼開發都用vim操作,顯得比較有B格。

技術之外

學如逆水行舟,不進則退。 程式設計師,是一個不斷自我學習,自我進步的過程,需要一直堅持學習,學習新知識,方能不被技術所淘汰。

不忘初心,堅持到底

面試了太多人,這些人不乏名校畢業,履歷光鮮,但都有個特點,就是轉行,有些從技術轉到產品,有些從技術轉到測試,慢慢在本行業失去了競爭力。

技術是我們的根本,這個一定不能放棄,即使已經做到了管理層,也請儘可能多的接觸程式碼。

目標、理想

理想是dream,可以實現不了,但它是支撐內心豐盈的信念。只有有了理想,才能設立目標,否則目標就總是在變,內心也有很多焦慮。

與君共勉。

相關文章