1. 程式人生 > >記憶體池,程序池,和執行緒池的比較分析

記憶體池,程序池,和執行緒池的比較分析

池的概念

由於伺服器的硬體資源“充裕”,那麼提高伺服器效能的一個很直接的方法就是以空間換時間,即“浪費”伺服器的硬體資源,以換取其執行效率。這就是池的概念。池是一組資源的集合,這組資源在伺服器啟動之初就完全被建立並初始化,這稱為靜態資源分配。當伺服器進入正式執行階段,即開始處理客戶請求的時候,如果它需要相關的資源,就可以直接從池中獲取,無需動態分配。很顯然,直接從池中取得所需資源比動態分配資源的速度要快得多,因為分配系統資源的系統呼叫都是很耗時的。當伺服器處理完一個客戶連線後,可以把相關的資源放回池中,無需執行系統呼叫來釋放資源。從最終效果來看,池相當於伺服器管理系統資源的應用設施,它避免了伺服器對核心的頻繁訪問。

池可以分為多種,常見的有記憶體池、程序池、執行緒池和連線池。

記憶體池

記憶體池是一種記憶體分配方式。通常我們習慣直接使用new、malloc等系統呼叫申請分配記憶體,這樣做的缺點在於:由於所申請記憶體塊的大小不定,當頻繁使用時會造成大量的記憶體碎片並進而降低效能。

記憶體池則是在真正使用記憶體之前,先申請分配一定數量的、大小相等(一般情況下)的記憶體塊留作備用。當有新的記憶體需求時,就從記憶體池中分出一部分記憶體塊,若記憶體塊不夠再繼續申請新的記憶體。這樣做的一個顯著優點是,使得記憶體分配效率得到提升。

程序池和執行緒池

程序池和執行緒池相似,所以這裡我們以程序池為例進行介紹。如沒有特殊宣告,下面對程序池的描述也適用於執行緒池。

程序池是由伺服器預先建立的一組子程序,這些子程序的數目在 3~10 個之間(當然這只是典型情況)。執行緒池中的執行緒數量應該和 CPU 數量差不多。

程序池中的所有子程序都執行著相同的程式碼,並具有相同的屬性,比如優先順序、 PGID 等。

當有新的任務來到時,主程序將通過某種方式選擇程序池中的某一個子程序來為之服務。相比於動態建立子程序,選擇一個已經存在的子程序的代價顯得小得多。至於主程序選擇哪個子程序來為新任務服務,則有兩種方法:

1)主程序使用某種演算法來主動選擇子程序。最簡單、最常用的演算法是隨機演算法和 Round Robin (輪流演算法)。

2)主程序和所有子程序通過一個共享的工作佇列來同步,子程序都睡眠在該工作佇列上。當有新的任務到來時,主程序將任務新增到工作佇列中。這將喚醒正在等待任務的子程序,不過只有一個子程序將獲得新任務的“接管權”,它可以從工作佇列中取出任務並執行之,而其他子程序將繼續睡眠在工作佇列上。

當選擇好子程序後,主程序還需要使用某種通知機制來告訴目標子程序有新任務需要處理,並傳遞必要的資料。最簡單的方式是,在父程序和子程序之間預先建立好一條管道,然後通過管道來實現所有的程序間通訊。在父執行緒和子執行緒之間傳遞資料就要簡單得多,因為我們可以把這些資料定義為全域性,那麼它們本身就是被所有執行緒共享的。

執行緒池主要用於:

1)需要大量的執行緒來完成任務,且完成任務的時間比較短。 比如WEB伺服器完成網頁請求這樣的任務,使用執行緒池技術是非常合適的。因為單個任務小,而任務數量巨大。但對於長時間的任務,比如一個Telnet連線請求,執行緒池的優點就不明顯了。因為Telnet會話時間比執行緒的建立時間大多了。

2)對效能要求苛刻的應用,比如要求伺服器迅速響應客戶請求。

3)接受突發性的大量請求,但不至於使伺服器因此產生大量執行緒的應用。