青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

CppExplore

一切像霧像雨又像風

  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
  29 隨筆 :: 0 文章 :: 280 評論 :: 0 Trackbacks

作者:CppExplore 網址:http://www.shnenglu.com/CppExplore/
服務器設計人員在一段時間的摸索后,都會發現:服務器性能的關鍵在于內存。從收包到解析,到消息內存的申請,到session結構內存的申請都要小心處理,盡量減少內存數據copy,減少內存動態申請,減少內存檢索。為達到這個目的,不同的地方有不同的方法,比如常見的包解析,使用緩沖區偏移以及長度來標識包內字段信息;內存使用量固定的系統,系統啟動就申請好所有需要的內存,初始化好,等待使用的時候直接使用;基于license控制的系統,根據license的數量,一次性申請固定數量內存等......。本文不再總結這些特性方案,重點說下常見的通用的內存池緩存技術。
    內存池可有效降低動態申請內存的次數,減少與內核態的交互,提升系統性能,減少內存碎片,增加內存空間使用率,避免內存泄漏的可能性,這么多的優點,沒有理由不在系統中使用該技術。
為了給內存池技術尋找基石,先從低層的內存管理看起。
硬件層略掉不談,可回顧《操作系統》。
一、linux內存管理策略
    linux低層采用三層結構,實際使用中可以方便映射到兩層或者三層結構,以適用不同的硬件結構。最下層的申請內存函數get_free_page。之上有三種類型的內存分配函數
(1)kmalloc類型。內核進程使用,基于slab技術,用于管理小于內存頁的內存申請。思想出發點和應用層面的內存緩沖池同出一轍。但它針對內核結構,特別處理,應用場景固定,不考慮釋放。不再深入探討。
(2)vmalloc類型。內核進程使用。用于申請不連續內存。
(3)brk/mmap類型。用戶進程使用。malloc/free實現的基礎。
有關詳細內容,推薦http://www.kerneltravel.net/journal/v/mem.htmhttp://www.kerneltravel.net上有不少內核相關知識。
二、malloc系統的內存管理策略
    malloc系統有自己的內存池管理策略,malloc的時候,檢測池中是否有足夠內存,有則直接分配,無則從內存中調用brk/mmap函數分配,一般小于等于128k(可設置)的內存,使用brk函數,此時堆向上(有人有的硬件或系統向下)增長,大于128k的內存使用mmap函數申請,此時堆的位置任意,無固定增長方向。free的時候,檢測標記是否是mmap申請,是則調用unmmap歸還給操作系統,非則檢測堆頂是否有大于128k的空間,有則通過brk歸還給操作系統,無則標記未使用,仍在glibc的管理下。glibc為申請的內存存儲多余的結構用于管理,因此即使是malloc(0),也會申請出內存(一般16字節,依賴于malloc的實現方式),在應用程序層面,malloc(0)申請出的內存大小是0,因為malloc返回的時候在實際的內存地址上加了16個字節偏移,而c99標準則規定malloc(0)的返回行為未定義。除了內存塊頭域,malloc系統還有紅黑樹結構保存內存塊信息,不同的實現又有不同的分配策略。頻繁直接調用malloc,會增加內存碎片,增加和內核態交互的可能性,降低系統性能。linux下的glibc多為Doug Lea實現,有興趣的可以去baidu、google。
三、應用層面的內存池管理
    跳過malloc,直接基于brk/mmap實現內存池,原理上是可行的,但實際中這種實現要追逐內核函數的升級,增加了維護成本,另增加了移植性的困難,據說squid的內存池是基于brk的,本人尚未閱讀squid源碼(了解磁盤緩存的最佳代碼,以后再詳細閱讀),不敢妄言。本文后面的討論的內存池都是基于malloc(或者new)實現。我們可以將內存池的實現分兩個類別來討論。
1、不定長內存池。典型的實現有apr_pool、obstack。優點是不需要為不同的數據類型創建不同的內存池,缺點是造成分配出的內存不能回收到池中。這是由于這種方案以session為粒度,以業務處理的層次性為設計基礎。
(1)apr_pool。apr全稱Apache portable Run-time libraries,Apache可移植運行庫。可以從http://www.apache.org/網站上下載到。apache以高性能、穩定性著稱,它所有模塊的內存申請都由內存池模塊apr_pool實現。有關apr_pool結構、實現的原理,http://blog.csdn.net/tingya/(apache源碼分析類別中的apache內存池實現內幕系列)已經有了詳細的講解,結合自己下載的源碼,已經足夠了。本人并不推薦去看這個blog和去看詳細的代碼數據結構以及邏輯。明白apr_pool實現的原理,知道如何使用就足夠了。深入細節只能是浪費腦細胞,當然完全憑個人興趣愛好了。
    這里舉例說下簡單的使用:

#include "apr_pools.h"
#include 
<stdio.h>
#include 
<new>

int main()
{
    apr_pool_t 
*root;
    apr_pool_initialize();
//初始化全局分配子(allocator),并為它設置mutext,以用于多線程環境,初始化全局池,指定全局分配

子的owner是全局池
    apr_pool_create(
&root,NULL);//創建根池(默認父池是全局池),根池生命期為進程生存期。分配子默認為全局分配子
    {
        apr_pool_t 
*child;
        apr_pool_create(
&child,root);//創建子池,指定父池為root。分配子默認為父池分配子
        void *pBuff=apr_palloc(child,sizeof(int));//從子池分配內存
        int *pInt=new (pBuff)  int(5);//隨便舉例下基于已分配內存后,面向對象構造函數的調用。
        printf("pInt=%d\n",*pInt);
        
{
            apr_pool_t 
*grandson;
            apr_pool_create(
&grandson,root);
            
void *pBuff2=apr_palloc(grandson,sizeof(int));
            
int *pInt2=new (pBuff2)  int(15);
            printf(
"pInt2=%d\n",*pInt2);    

            apr_pool_destroy(grandson);
        }

        apr_pool_destroy(child);
//釋放子池,將內存歸還給分配子
    }

    apr_pool_destroy(root);
//釋放父池,
    apr_pool_terminate();//釋放全局池,釋放全局allocator,將內存歸還給系統
    return 1;
}

    apr_pool中主要有3個對象,allocator、pool、block。pool從allocator申請內存,pool銷毀的時候把內存歸還allocator,allocator銷毀的時候把內存歸還給系統,allocator有一個owner成員,是一個pool對象,allocator的owner銷毀的時候,allocator被銷毀。在apr_pool中并無block這個單詞出現,這里大家可以把從pool從申請的內存稱為block,使用apr_palloc申請block,block只能被申請,沒有釋放函數,只能等pool銷毀的時候才能把內存歸還給allocator,用于allocator以后的pool再次申請。
    我給的例子中并沒有出現創建allocator的函數,而是使用的默認全局allocator。apr_pool提供了一系列函數操作allocator,可以自己調用這些函數:
apr_allocator_create
apr_allocator_destroy
apr_allocator_alloc
apr_allocator_free
創建銷毀allocator
apr_allocator_owner_set
apr_allocator_owner_get
設置獲取owner
apr_allocator_max_free_set 設置pool銷毀的時候內存是否直接歸還到操作系統的閾值
apr_allocator_mutex_set
apr_allocator_mutex_get
設置獲取mutex,用于多線程

另外還有設置清理函數啊等等,不說了。自己去看include里的頭文件好了:apr_pool.h和apr_allocator.h兩個。源碼.c文件里,APR_DECLARE宏聲明的函數即是暴露給外部使用的函數。大家也可以仿造Loki(后文將介紹Loki)寫個頂層類重載operator new操作子,其中調用apr_palloc,使用到的數據結構繼承該類,則自動從pool中申請內存,如要完善的地方很多,自行去研究吧。
    可以看出來apr_pool的一個大缺點就是從池中申請的內存不能歸還給內存池,只能等pool銷毀的時候才能歸還。為了彌補這個缺點,apr_pool的實際使用中,可以申請擁有不同生命周期的內存池(類似與上面的例子程序中不同的大括號代表不同的生命周期,實際中,盡可以把大括號中的內容想象成不同的線程中的......),以便盡可能快的回收不再使用的內存。實際中apache也是這么做的。因此apr_pool比較適合用于內存使用的生命期有明顯層次的情況。
    至于擔心allocator中的內存一旦申請就再也不歸還給操作系統(當然最后進程退出的時候你可以調用銷毀allocator歸還,實際中網絡服務程序都是一直運行的,找不到銷毀的時機)的問題,就是杞人憂天了,如果在某一時刻,系統占用的內存達到頂峰,意味著以后還會有這種情況。是否能接受這個解釋,就看個人的看法和系統的業務需求了,不能接受,就使用其它的內存池。個人覺得apr_pool還是很不錯的,很多服務系統的應用場景都適用。
(2)obstack。glibc自帶的內存池。原理與apr_pool相同。詳細使用文檔可以參閱
http://www.gnu.org/software/libc/manual/html_node/Obstacks.html。推薦apr_pool,這個就不再多說了。
(3)AutoFreeAlloc。許式偉的專欄http://blog.csdn.net/xushiweizh/category/265099.aspx
    這個內存池我不看好。這個也屬于一個變長的內存池,內存申請類似與apr_pool的pool/block層面,一次申請大內存作為pool,用于block的申請,同樣block不回收,等pool銷毀的時候直接歸還給操作系統。這個內存池的方案,有apr_pool中block不能回收到pool的缺點,沒有pool回收到allocator,以供下次繼續使用的優點,不支持多線程。適合于單線程,集中使用內存的場景,意義不是很大。

posted on 2008-02-18 16:55 cppexplore 閱讀(15095) 評論(17)  編輯 收藏 引用

評論

# re: 【原創】系統設計之 內存管理 2008-02-18 17:29 CornerZhang
謝謝!看來這個apr_pool不錯.  回復  更多評論
  

# re: 【原創】系統設計之 內存管理 2008-02-18 18:39 eXile
對于最后一個AutoFreeAlloc, 我碰巧也研究過, 其實對于你說的"沒有pool回收到allocator,以供下次繼續使用"的問題,它最近的實現中已經解決了.
在c++ 標準庫實現SGI STL中還有一種內存池的實現, 就是用一系列固定長的內存池來實現一個不定長的內存池, 它曾經是gcc3中stl的默認實現, 但在gcc4中不再使用, 理由是在多線程情況下優化并不明顯, 線程鎖反而成為瓶頸. 所以有時候一個線程一個內存池也是一個選擇.
  回復  更多評論
  

# re: 【原創】系統設計之 內存管理[未登錄] 2008-02-18 20:11 CppExplore
@CornerZhang
呵呵,apache很成功,apr_pool自然不會差。

@eXile
AutoFreeAlloc的發展方向應該就是apr_pool。apr_pool已經把變長的內存池發展到極致,當然這是當前看到的,或許以后有內存池會把變長內存池推到一個新的高度。:)
支持多線程的內存池都是從單線程加鎖機制實現的,都提供無鎖的實現。apr_pool也是,顯式構造allocator后不調用apr_allocator_mutex_set就是無鎖的實現。
后面的boost和loki的無鎖和有鎖的實現區別更是明顯。   回復  更多評論
  

# re: 【原創】系統設計之 內存管理 2008-02-19 12:33 空明流轉
多線程的池子Lock-Free的解決辦法很有前途。原子操作速度很快,沒有鎖的消耗。  回復  更多評論
  

# re: 【原創】系統設計之 內存管理[未登錄] 2008-02-19 15:59 cppexplore
@空明流轉
這個現在還是只能停留在美好的展望階段,不過這一天的到來不遠了。
  回復  更多評論
  

# re: 【原創】系統設計之 內存管理(一) 2008-02-19 21:49 空明流轉
展望已經不是展望了。就是庫中用的很少,但是不排除一些服務器上已經用了這個玩意了。  回復  更多評論
  

# re: 【原創】系統設計之 內存管理(一) 2008-03-19 16:43 xushiwei
關于AutoFreeAlloc,推薦博主看一下以下兩篇:

http://cpp.winxgui.com/cn:a-general-gc-allocator-scopealloc
http://cpp.winxgui.com/cn:lock-free-gc-allocator
  回復  更多評論
  

# re: 【原創】系統設計之 內存管理(一) 2008-03-19 16:45 xushiwei
另外,AutoFreeAlloc與apr pools的性能對比:
http://cpp.winxgui.com/cn:gc-allocators-vs-apr-pools  回復  更多評論
  

# re: 【原創】系統設計之 內存管理(一) 2008-03-19 17:34 cppexplore
@xushiwei
麻煩做下修改再測試:
void doAprPools1(LogT& log)
{
log.print("===== APR Pools =====\n");
std::PerformanceCounter counter;
for (int i = 0; i < N; ++i)
{
apr_pool_t* alloc;
apr_pool_create(&alloc, m_pool);
int* p = (int*)apr_palloc(alloc, sizeof(int));
apr_pool_destroy(alloc);
}
counter.trace(log);
}
改成
void doAprPools1(LogT& log)
{
int i;
apr_pool_t* alloc;
apr_pool_create(&alloc, m_pool);
for (i = 0; i < N; ++i)
{
int* p = (int*)apr_palloc(alloc, sizeof(int));
}
apr_pool_destroy(alloc);

apr_pool_t* alloc2;
apr_pool_create(&alloc2, m_pool);
log.print("===== APR Pools =====\n");
std::PerformanceCounter counter;
for (i = 0; i < N; ++i)
{
int* p = (int*)apr_palloc(alloc2, sizeof(int));
}
counter.trace(log);
apr_pool_destroy(alloc2);
}
至于線程鎖的使用開銷,這里就先不考慮了。“apr_pool也是,顯式構造allocator后不調用apr_allocator_mutex_set就是無鎖的實現。 ”  回復  更多評論
  

# re: 【原創】系統設計之 內存管理(一) 2008-03-23 13:51 xushiwei
to cppexplore: 請留意我的測試意圖。  回復  更多評論
  

# re: 【原創】系統設計之 內存管理(一) 2008-03-24 12:28 cppexplore
@xushiwei
你的測試代碼對apr-pool不公平,首先(1)作為服務器,關心是長期運行后的性能,而不是開始幾個請求的性能,一個服務器可能365天無間斷服務,而只拿系統啟動2分鐘的性能來衡量1年的性能顯然不合適,而apr-pool開始申請內存是直接new,釋放的時候才組織內存池結構。(2)對于集中處理的情況(類似你的測試代碼),內存的申請是從同一個池中申請的,而不是申請一塊內存,就必須先申請一個池。
你的測試代碼,(1)是針對apr-pool性能最差的建池階段 (2)每申請一塊內存,反復的從allocator創建銷毀內存池,和實際的使用不相符
而你的內存池,則沒有建池階段,直接棧中建池,我認為用上面寫過apr-pool測試代碼用來測試,才對apr-pool公平。

其實我覺得對內存池做這種性能對比沒意義,首先這是變長內存池,不需要考慮釋放,性能對比也就只是測試申請階段的性能,而變長內存池都是在已有大內存上的指針滑動,都是常數步驟內完成。因此和算法之間對比性能不同,完善的內存池之間根本就沒有性能比較的必要。  回復  更多評論
  

# re: 【原創】系統設計之 內存管理(一) 2008-03-24 15:40 xushiwei
to cppexplore: 我的測試分了兩種情況,我想你關注的是測試2的對比數據。測試1在實際中并不常見,只是我要看的是allocator的伸縮性。至于內存池的效率,我的觀念和你相反,既然它是基礎設施,那么它的性能調優是非常關鍵的,比你去優化任何其他東西都來得有效。而算法之間我比較關心復雜度,而不是非常關心性能調優(微調)。  回復  更多評論
  

# re: 【原創】系統設計之 內存管理(一)[未登錄] 2008-03-25 09:04 cppexplore
@xushiwei
“它是基礎設施,那么它的性能調優是非常關鍵的”,這句話我不反對,雖然我認為對變長內存池沒必要。不過你的測試代碼并沒有反映apr_pool的真實性能。  回復  更多評論
  

# re: 【原創】系統設計之 內存管理(一) 2008-04-25 16:19 Simon
不知道apr_pool使用在商業軟件中是否有版權問題?  回復  更多評論
  

# re: 【原創】系統設計之 內存管理(一) 2008-04-25 16:53 cppexplore
它使用Apache License。允許免費修改重發布,允許商業使用,允許不公布修改后的源代碼。  回復  更多評論
  

# re: 【原創】技術系列之 內存管理(一) 2008-10-23 13:23 cui
apr_pool 不是預先申請大塊內存嗎? 不然變長內存池怎么實現?  回復  更多評論
  

# re: 【原創】技術系列之 內存管理(一) 2009-03-23 17:41 舵手
內存,內存。。。  回復  更多評論
  

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美在线免费观看| 久久综合婷婷| 亚洲视频一区二区| 国产精品影音先锋| 久久久精品一品道一区| 欧美成人亚洲成人日韩成人| 在线午夜精品自拍| 久久久999精品视频| 一本久道久久综合狠狠爱| 亚洲深夜福利在线| 日韩视频一区二区在线观看| 亚洲香蕉成视频在线观看| 精品成人一区二区| 亚洲一区二区三区四区中文| 亚洲人成人一区二区三区| 欧美精品一区二区三区很污很色的 | 午夜精品一区二区三区在线| 亚洲精品乱码| 午夜在线观看免费一区| 久久在线视频在线| 在线成人激情黄色| 99视频一区| 亚洲激情一区二区三区| 亚洲在线观看免费视频| 99精品欧美一区| 久久亚洲综合色| 猫咪成人在线观看| 亚洲福利视频网| 亚洲人成免费| 久久久精品一区| 久久精品一本久久99精品| 久热精品在线视频| 麻豆久久精品| 欧美福利电影网| 国产精品狼人久久影院观看方式| 久久久久免费| 一区二区在线视频| 久久免费视频在线| 久久激情视频免费观看| 国产精品theporn| 午夜精品久久久久久久男人的天堂| 亚洲国产另类久久精品| 欧美精品三级日韩久久| 日韩午夜在线观看视频| 亚洲一区二区三区精品动漫| 国产精品啊啊啊| 午夜精品久久久久久久久久久| 一区二区激情小说| 国产精品久久一区主播| 日韩视频免费在线| 欧美在线短视频| 红桃视频成人| 欧美日本一区二区视频在线观看| 免费人成精品欧美精品| 亚洲自拍都市欧美小说| 在线免费观看欧美| 欧美黑人多人双交| 正在播放亚洲| 久久久久久久一区二区| 亚洲激情在线视频| 激情另类综合| 欧美日韩国产精品一区| 午夜精品久久久久久| 亚洲欧洲日韩综合二区| 久久精品国产99精品国产亚洲性色 | 亚洲精品黄色| 美女被久久久| 久久免费观看视频| 亚洲女女女同性video| 91久久精品国产91久久| 激情久久婷婷| 韩曰欧美视频免费观看| 国产麻豆日韩| 精品99视频| 国产综合第一页| 国产午夜精品视频免费不卡69堂| 欧美三日本三级少妇三99| 欧美三日本三级少妇三2023| 欧美日韩人人澡狠狠躁视频| 欧美日韩一区二区三区在线| 欧美国产一区二区| 欧美片在线观看| 国产美女高潮久久白浆| 国产精品夜色7777狼人| 国产乱肥老妇国产一区二| 国产精品尤物| 国产亚洲福利社区一区| 国产亚洲欧美日韩一区二区| 国产日韩欧美中文在线播放| 伊人久久大香线蕉综合热线| 激情成人av在线| 亚洲一区二区三区在线播放| 亚洲欧美一区二区三区久久| 久久精品国产在热久久| 亚洲七七久久综合桃花剧情介绍| 亚洲国产三级网| 欧美一级大片在线观看| 欧美伦理a级免费电影| 国产亚洲欧美一区| 亚洲欧美欧美一区二区三区| 久久影院亚洲| 久久精品一区二区三区中文字幕| 欧美亚男人的天堂| 欧美成va人片在线观看| 狠狠入ady亚洲精品| 中国成人黄色视屏| 亚洲精品国产精品久久清纯直播 | 久久高清一区| 亚洲一级免费视频| 国产精品福利av| 一区二区三区免费网站| 亚洲国产精品日韩| 久久久国产成人精品| 国产精品一二三| 午夜精品久久久久久久久久久| 亚洲精品欧美在线| 欧美激情麻豆| 在线综合+亚洲+欧美中文字幕| 欧美va亚洲va日韩∨a综合色| 久久久青草青青国产亚洲免观| 精品动漫3d一区二区三区| 免费一级欧美片在线播放| 久久婷婷国产综合国色天香| 国产日韩精品视频一区二区三区| 一区二区三区高清在线| 在线视频免费在线观看一区二区| 国产精品一区二区在线| 久久亚洲国产成人| 另类天堂视频在线观看| 日韩手机在线导航| 亚洲免费在线播放| 99精品免费网| 欧美91精品| 久久av最新网址| 欧美日一区二区三区在线观看国产免| 久久精品噜噜噜成人av农村| 欧美日韩八区| 免费观看成人网| 国产精品久久久一区麻豆最新章节 | 欧美午夜久久| 亚洲黄色成人久久久| 国产日本欧美一区二区| 久久综合综合久久综合| 欧美天堂在线观看| 亚洲每日在线| 亚洲午夜高清视频| 国产精品v欧美精品∨日韩| 亚洲精选在线观看| 亚洲一区在线直播| 欧美视频你懂的| 亚洲作爱视频| 亚洲女人天堂成人av在线| 欧美视频一区在线观看| 亚洲午夜91| 久久国产免费看| 国产一区在线视频| 久久久噜噜噜久久中文字幕色伊伊| 午夜视频在线观看一区| 国产一区二区三区精品欧美日韩一区二区三区 | 亚洲欧美日韩成人| 久久国产精品久久久| 国产欧美一区二区三区国产幕精品| 99精品国产一区二区青青牛奶| 亚洲图片激情小说| 国产欧美精品国产国产专区| 午夜伦欧美伦电影理论片| 看欧美日韩国产| 99精品欧美| 精品88久久久久88久久久| 欧美国产第一页| 亚洲一区二区三区中文字幕| 久久激情综合网| 亚洲人成亚洲人成在线观看图片| 国产精品啊啊啊| 欧美91精品| 欧美一区二区在线视频| 欧美激情一区二区三区全黄| 亚洲午夜女主播在线直播| 亚洲成色精品| 亚洲成色777777在线观看影院 | 亚洲精品中文字幕在线| 欧美顶级大胆免费视频| 亚洲欧美视频在线观看| 亚洲国产综合91精品麻豆| 欧美在线免费视屏| 亚洲一区二区视频| 99re6热只有精品免费观看 | 国产亚洲欧洲| 国产精品亚洲综合天堂夜夜 | 日韩视频一区| 欧美黄色日本| 免费人成网站在线观看欧美高清| 性亚洲最疯狂xxxx高清| 亚洲欧美日韩国产成人精品影院 | 一区二区不卡在线视频 午夜欧美不卡'| 久久精品在线| 亚洲茄子视频| 欧美亚洲一区二区在线| 久久躁狠狠躁夜夜爽| 欧美日韩不卡|