記憶體池、程式池、執行緒池

守護大白菜發表於2017-10-19

轉自  http://blog.csdn.net/u011012049/article/details/48436427

池的概念

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

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


記憶體池

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

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


程式池和執行緒池

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

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

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

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

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

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

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

執行緒池主要用於:

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

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

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

相關文章