筆者受公司委托對 2.6 的內核作了一個性能評估,評測的對象包括進程切換性能,線程切換性能,網絡性能,內存讀取速度,文件系統性能幾個方面。結果表明,在工作站的模式下 2.6 的內核大多數指標比不上 2.4 內核的性能。在服務器模式下, 2.6 內核才開始有優勢。同時,本文使用 FreeBSD 作為參照比較對象。
Linux2.6 內核的新特性
內存管理
1 .搶占式內存
2.6 版本以前的 Linux 內核是不允許對一個被系統調用并處于運行狀態的進程進行調度的。這意味著一旦系統調用中有某個任務正在執行,那么該任務會控制處理器直到系統調用結束,而不管其使用處理器時間的長短。(2.4是分時的,為什么網上的系統說“直到系統調用結束” ??)
2.6 版內核中內存是可搶占的。一些人認為可搶占式內存使 Linux 2.6 內核在一些時效性較強的事件中比 2.4 版內核具有更好的響應能力。為實現搶占式內存, Linux 2.6 內核中的代碼被設置了搶占點,這意味著調度程序會中止正在運行的進程,而來執行優先級更高的進程。在系統調用過程中, Linux 2.6 內核會定時地檢查搶占點,以避免不合理的延遲發生。而在檢查過程中,調度進程很可能就會中止當前進程來讓另一個進程運行。
實際上,測試表明搶占內核使工作站環境下的應用程序速度變慢。
2 .引入內存池機制
2.6 版內核的開發過程引入了內存池以滿足不間斷地進行內存分配。其思想是預先分配一個內存池,并保留到真正需要的時候。 哈哈,其結果是系統一啟動,大量的內存就沒有了。
3 .改善虛擬內存
2.6 版內核改善了虛擬內存在一定程度負載下的性能。 通過反向地址映射減少了系統的開銷。
Linux 內核工作于虛擬內存模式時,每一個虛擬頁對應一個相應系統內存的物理頁。虛擬頁和物理頁之間的地址轉換由硬件頁表來完成。但是這種“虛擬到物理”的頁映射不總是一一對應的,多個虛擬頁有可能指向同一個物理頁。這種情況下,內核想要釋放特定的物理頁就必須遍歷所有的進程頁表記錄來查找指向這個物理頁的引用,只有在引用數達到 0 時才能釋放該物理頁。負載較高時,這會讓虛擬內存變得非常慢。
反向地址映射補丁通過在結構頁引入一個叫做 pte_chain 的數據結構來解決這一問題。
不過,這種方法存在一個指針開銷問題。系統中的每一個結構頁都必須有一個額外的、用于 pte_chain 的結構。一個 256MB 內存的系統有 64K 個物理頁,這就需要有 64KB* ( sizeof ( struct pte_chain ))的內存被分配用于 pte_chain 的結構。
使用了這項技術, r-map 的性能,尤其是高負載的高端系統,相對于 2.4 版內核的虛擬內存系統還是有了顯著地提高。
4 .共享內存的改進
Linux 2.6 內核為多程序提供了一種不同的途徑,即 NUMA ( Non Uniform Memory Access )。這種方法中,內存和處理器是相互連接的,但對于每一個處理器,某些內存是“關閉”的,而某些內存則“更遠”。這意味著當內存競爭出現時,“更近”的處理器對就近的內存有更高的使用權。 2.6 版內核提供了一套功能來定義內存和處理器之間的拓撲關系。調度程序可以利用這些信息來為任務分配本地內存。這樣將減少內存競爭造成的瓶頸,提高吞吐量。
驅動程序
1 .中斷例程的改進
在 2.6 版內核中,驅動程序如果要從一個設備上發出中斷需要返回 IRQ_HANDLED ,否則返回 IRQ_NONE 。這樣可以幫助內核的 IRQ 層清楚地識別出哪個驅動程序正在處理哪個特定的中斷。 如果一個中斷請求不斷到來,而且沒有注冊那個設備的處理程序,內核就會忽略來自該設備的中斷。
2 .驅動程序移植
相對于 2.4 版內核來說, 2.6 版內核改進了內核編譯系統,從而獲得更快的編譯速度。 2.6 版內核的編譯系統加入了改進的圖形化工具 make xconfig (需要 Qt 庫)和 make gconfig
內核模塊加載器也在 2.6 版內核中被完全實現,使得模塊編譯機制相對于 2.4 版內核有了很大的不同。原來 2.4 版內核中的模塊工具不能用來加載或卸載 2.6 版內核的模塊,需要一組新的模塊工具來完成模塊的加載和卸載。這個新的模塊加載工具會盡量減少在一個設備仍被使用的情況下,相應的模塊卻被卸載的沖突發生,而是在確認這些模塊已經沒有任何設備在使用后再卸載掉。產生這種沖突的原因之一是,模塊使用計數是由模塊代碼自己來控制的。在 2.6 版內核中,模塊不再需要對引用計數進行加減,這些工作將在模塊代碼外部進行。
進程管理
1 .新調度器算法
2.6 版本的 Linux 內核使用了新的調度器算法,稱為 O ( 1 )算法,它在高負載的情況下執行得非常出色,并在有多個處理器時能夠很好地擴展。
2.4 版本的調度器中,時間片重算算法要求在所有的進程都用盡它們的時間片后,新時間片才會被重新計算。在一個多處理器系統中,當進程用完它們的時間片后不得不等待重算,以得到新的時間片,從而導致大部分處理器處于空閑狀態,影響 SMP 的效率。此外,當空閑處理器開始執行那些時間片尚未用盡的、處于等待狀態的進程時,會導致進程開始在處理器之間“跳躍”。當一個高優先級進程或交互式進程發生跳躍時,整個系統的性能就會受到影響。
新調度器解決上述問題的方法是,基于每個 CPU 來分布時間片,并取消全局同步和重算循環。調度器使用了兩個優先級數組,即活動數組和過期數組,可以通過指針來訪問它們。活動數組中包含所有映射到某個 CPU 且時間片尚未用盡的任務。過期數組中包含時間片已經用盡的所有任務的有序列表。如果所有活動任務的時間片都已用盡,那么指向這兩個數組的指針互換,包含準備運行任務的過期數組成為活動數組,而空的活動數組成為包含過期任務的新數組。數組的索引存儲在一個 64 位的位圖中,所以很容易找到優先級的任務。
新調度器的主要優點包括:
◆ SMP 效率 如果有工作需要完成,所有處理器都會工作。
◆ 等待進程 沒有進程需要長時間地等待處理器,也沒有進程會無端地占用大量的 CPU 時間。
◆ SMP 進程映射 進程只映射到一個 CPU ,而且不會在 CPU 之間跳躍。
◆ 優先級 非重要任務的優先級低,反之亦然。
◆ 負載平衡 調度器會降低那些超出處理器負載能力的進程的優先級。
◆ 交互性能 即使在高負載的情況下,系統花費很長時間來響應鼠標點擊或鍵盤輸入的情況也不會再發生。
2 .高效的調度程序
2.6 版內核中,進程調度經過重新編寫,調度程序不需每次都掃描所有的任務,而是在一個任務變成就緒狀態時將其放到一個名為“當前”的隊列中。當進程調度程序運行時,只選擇隊列中有利的任務來執行。這樣,調度可以在一個恒定的時間里完成。當任務執行時,它會得到一個時間段,或者在其轉到另一線程之前得到一段時間的處理器使用權。當時間段用完后,任務會被轉移到另一個名為“過期”的隊列中。在該隊列中,任務會根據其優先級進行排序。
從某種意義上說,所有位于“當前”隊列的任務都將被執行,并被轉移到“過期”隊列中。當這種事情發生時,隊列就會進行切換,原來的“過期”隊列成為“當前”隊列,而空的“當前”隊列則變成“過期”隊列。由于在新的“當前”隊列中,任務已經被排列好,調度程序現在使用簡單的隊列算法,即總是取當前隊列的個任務進行執行。這個新過程要比老過程快得多。
3 .新的同步措施
多進程應用程序有時需要共享一些資源,比如共享內存或設備。為了避免競爭的出現,程序員會使用一個名為互斥的功能來確保同一時刻只有一個任務在使用資源。到目前為止, Linux 還是通過一個包含在內核中的系統調用來完成互斥的實現,并由該系統調用決定一個線程是等待還是繼續執行。
Linux 2.6 內核支持 FUSM ( Fast User-Space Mutex )。這個新功能會檢查用戶的空間,查看是否有等待的情況出現,并且只有在線程需要等待時才進行系統調用。這樣當不需要等待時,就會避免不必要的系統調用,以節約時間。該功能也使用優先級調度,以便在出現競爭時決定哪一個線程可以被執行。
測試報告
測試平臺:
硬件:
2 AMD XP 2500+ / Intel PV 3G (HT支持)
2 DDR RAM 256M 333Mhz
2 硬盤 Maxtor 40G 7200rpm/s
2 主板 MSI KT4AV
2 100M 以太網卡
軟件
2 GCC 3.4.2
2 Slackware 10.1
2 文件系統 ReiserFS
參考平臺
FreeBSD5.3
比較對象;
2 kernel 2.4.29
2 kernel 2.6.10
2 FreeBSD 5.3
說明:
所有內核都根據平臺屬性重新編譯
測試工具
2 lmbench 用于系統性能整體測試
2 forkbomb 進程壓力測試
2 Netperf 網路性能測試
Linux 2.6 編譯
首先獲取的 kernel 代碼
linux-2.6.10.tar.bz2
解壓源代碼
tar zjvf linux-2.6.10.tar.bz2
進行配置:
make xconfig
測試使用 SSH 客戶端在字符界面下進行。
比較結果
內核的大小
根據機器的硬件狀況重新編譯了內核,編譯的結果如下:(未壓縮)
啟動內存大小
系統啟動后,開啟了12路的VoIP網關程序。結果,內存的消耗狀況如下,大家不要害怕,這還能稱為嵌入式系統嗎?
線程創建速度
pthread 線程創建測試, BSD 是的贏家,幾乎不需要時間
內存訪問速度
內存訪問測試,三者速度差多,整體來看 2.4 快于 bsd 快于 2.6
文件訪問
文件訪問速度 BSD>2.4>2.6
網絡流量
網絡速度: BSD 明顯優勢
socket 創建速度
socket 函數創建的時間: BSD 優于 2.6 優于 2.4
bind 函數訪問時間
在小負載下,三者表現比較接近,時間是常數在大負載下 2.4.29 變慢
bind 函數平均時間 () |
(3000socket) |
(10000socket) |
2.4.29 |
O(1) |
O(n) |
2.6.10 |
O(1) |
O(1) |
FreeBSD5.3 |
O(1) |
O(1) |