高性能服務器架構 第一篇

 

轉自:http://www.doserv.com/article/2012/0831/5299117.shtml

 

本文不會涉及到多任務應用程序,在單個程序裏同時處理多個任務現在已經很常見。比如你的瀏覽器可能就在做一些並行處理,但是這類並行程序設計沒有多大挑戰性. 真正的挑戰出現在服務器的架構設計對性能產生制約時,如何通過改善架構來提升系統性能. 對於在擁有上G內存和G赫茲CPU上運行的瀏覽器來說,通過DSL進行多個併發下載任務不會有如此的挑戰性. 這裏,應用的焦點不在於通過吸管小口吮吸,而是如何通過水龍頭大口暢飲,這裏麻煩是如何解決在硬件性能的制約.(作者的意思應該是怎麼通過網絡硬件的改善來增大流量)

一些人可能會對我的某些觀點和建議發出置疑,或者自認爲有更好的方法, 這是無法避免的. 在本文中我不想扮演上帝的角色;這裏所談論的是我自己的一些經驗,這些經驗對我來說, 不僅在提高服務器性能上有效,而且在降低調試困難度和增加系統的可擴展性上也有作用. 但是對某些人的系統可能會有所不同. 如果有其它更適合於你的方法,那實在是很不錯. 但是值得注意的是,對本文中所提出的每一條建議的其它一些可替代方案,我經過實驗得出的結論都是悲觀的. 你自己的小聰明在這些實驗中或許有更好的表現,但是如果因此慫恿我在這裏建議讀者這麼做,可能會引起無辜讀者的反感. 你並不想惹怒讀者,對吧?

本文的其餘部分將主要說明影響服務器性能的四大殺手:

1) 數據拷貝Data Copies -- 技巧什麼的

2) 環境切換Context Switches -- 理性創建線程

3) 內存分配Memory allocation -- 內存池

4) 鎖競爭Lock contention -- 沒有好的辦法, 和具體的業務特點, 軟件的設計結構有密切的聯繫

在文章結尾部分還會提出其它一些比較重要的因素,但是上面的四點是主要因素. 如果服務器在處理大部分請求時能夠做到沒有數據拷貝,沒有環境切換,沒有內存分配,沒有鎖競爭,那麼我敢保證你的服務器的性能一定很出色.

數據拷貝Data Copies

本節會有點短,因爲大多數人在數據拷貝上吸取過教訓. 幾乎每個人都知道產生數據拷貝是不對的,這點是顯而易見的,在你的職業生涯中, 你很早就會見識過它;而且遇到過這個問題,因爲10年前就有人開始說這個詞。對我來說確實如此. 現今,幾乎每個大學課程和幾乎所有how-to文檔中都提到了它. 甚至在某些商業宣傳冊中,"零拷貝" 都是個流行用語. 儘管數據拷貝的壞處顯而易見,但是還是會有人忽視它. 因爲產生數據拷貝的代碼常常隱藏很深且帶有僞裝,你知道你所調用的庫或驅動的代碼會進行數據拷貝嗎?答案往往超出想象. 猜猜"程序I/O"在計算機上到底指什麼?哈希函數是僞裝的數據拷貝的例子,它有帶拷貝的內存訪問消耗和更多的計算. 曾經指出哈希算法是一種有效的"拷貝"似乎能夠被避免,但據我所知,有一些非常聰明的人說過要做到這一點是相當困難的. 如果想真正去除數據拷貝,不管是因爲影響了服務器性能,還是想在黑客大會上展示"零複製"技術,你必須自己跟蹤可能發生數據拷貝的所有地方,而不是輕信宣傳.

有一種可以避免數據拷貝的方法是使用buffer的描述符(或者buffer chains的描述符)來取代直接使用buffer指針,每個buffer描述符應該由以下元素組成:

一個指向buffer的指針和整個buffer的長度

一個指向buffer中真實數據的指針和真實數據的長度,或者長度的偏移

以雙向鏈表的形式提供指向其它buffer的指針

一個引用計數

現在,代碼可以簡單的在相應的描述符上增加引用計數來代替內存中數據的拷貝. 這種做法在某些條件下表現的相當好,包括在典型的網絡協議棧的操作上,但有些情況下這做法也令人很頭大. 一般來說,在buffer chains的開頭和結尾增加buffer很容易,對整個buffer增加引用計數,以及對buffer chains的即刻釋放也很容易. 在chains的中間增加buffer,一塊一塊的釋放buffer,或者對部分buffer增加引用技術則比較困難. 而分割,組合chains會讓人立馬崩潰.

我不建議在任何情況下都使用這種技術,因爲當你想在鏈上搜索你想要的一個塊時,就不得不遍歷一遍描述符鏈,這甚至比數據拷貝更糟糕. 最適用這種技術地方是在程序中大的數據塊上,這些大數據塊應該按照上面所說的那樣獨立的分配描述符,以避免發生拷貝,也能避免影響服務器其它部分的工作. (大數據塊拷貝很消耗CPU,會影響其它併發線程的運行)

關於數據拷貝最後要指出的是:在避免數據拷貝時不要走極端. 我看到過太多的代碼爲了避免數據拷貝,最後結果反而比拷貝數據更糟糕,比如產生環境切換或者一個大的I/O請求被分解了. 數據拷貝是昂貴的,但是在避免它時,是收益遞減的(意思是做過頭了,效果反而不好). 爲了除去最後少量的數據拷貝而改變代碼,繼而讓代碼複雜度翻番,不如把時間花在其它方面.

 

發佈了17 篇原創文章 · 獲贊 6 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章