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

隨筆-91  評(píng)論-137  文章-0  trackbacks-0
內(nèi)存池的作用:
減少內(nèi)存碎片,提高性能。

首先不得不提的是Win32和x64中對(duì)于指針的長(zhǎng)度是不同的,在Win32中一個(gè)指針占4字節(jié),而在x64中一個(gè)指針占8字節(jié)。也正是不清楚這一點(diǎn),當(dāng)我在x64中將指針作為4字節(jié)修改造成其他數(shù)據(jù)異常。

首先我們先來(lái)定義三個(gè)宏
            #define ALIGN     sizeof(void*)
            #define MAX_BYTES 128
            #define MAX_COUNT (MAX_BYTES / ALIGN)
正如前面所說(shuō)的,為了兼容Win32與x64應(yīng)此我們將要申請(qǐng)的內(nèi)存按void*的大小來(lái)對(duì)齊。正如前面所說(shuō)的,我們認(rèn)為小于128字節(jié)的內(nèi)存為小內(nèi)存,會(huì)產(chǎn)生內(nèi)存碎片,應(yīng)此在申請(qǐng)時(shí)應(yīng)該勁量申請(qǐng)一塊較大的內(nèi)存而將其中的一小塊分配給他。

然后讓我們來(lái)看一下內(nèi)存池中的成員變量
            struct obj
            {
                obj* next;
            };

            struct block
            {
                block* next;
                void*  data;
            };

            obj*   chunk_list[MAX_COUNT];
            size_t chunk_count;
            block* free_list;
這里使用obj結(jié)構(gòu)來(lái)存儲(chǔ)已釋放內(nèi)存的列表,這樣做的好處是可以更節(jié)省內(nèi)存。在Win32中使用這塊內(nèi)存的前4字節(jié)來(lái)指向下一個(gè)節(jié)點(diǎn),而在x64中使用這塊內(nèi)存的前8字節(jié)來(lái)指向下一個(gè)節(jié)點(diǎn)。
chunk_list:保存通過(guò)deallocate或refill中釋放或是新申請(qǐng)的內(nèi)存塊列表,deallocate和refill將會(huì)在下文中介紹。
chunk_count:內(nèi)存塊列表中已有的內(nèi)存塊數(shù)量。
free_list:保存了通過(guò)malloc申請(qǐng)內(nèi)存塊的鏈表。

下面我們來(lái)看一下內(nèi)存池的構(gòu)造函數(shù)與析構(gòu)函數(shù)
            MemoryPool() : free_list(0), chunk_count(0)
            {
                for(int i = 0; i < MAX_COUNT; ++i) chunk_list[i] = 0;
            }

            ~MemoryPool()
            {
                block* current = free_list;
                while(current)
                {
                    block* next = current->next;
                    free(current->data);
                    free(current);
                    current = next;
                }
            }
構(gòu)造函數(shù)中初始化free_list和chunk_count為0,并初始化chunk_list為一個(gè)空列表。而在析構(gòu)函數(shù)中我們必須釋放每一塊通過(guò)malloc申請(qǐng)的大內(nèi)存塊。

接下來(lái)是內(nèi)存的申請(qǐng)
            template <typename T>
            T* allocate(size_t n, void(*h)(size_t))
            {
                if(n == 0) return 0;
                if(n > MAX_BYTES)
                {
                    T* p = (T*)malloc(n);
                    while(p == 0)
                    {
                        h(n);
                        p = (T*)malloc(n);
                    }
                    return p;
                }
                const int i = INDEX(ROUND_UP(n));
                obj* p = chunk_list[i];
                if(p == 0)
                {
                    return refill<T>(i, h);
                }
                chunk_list[i] = p->next;
                return reinterpret_cast<T*>(p);
            }
值得注意的是,在調(diào)用時(shí)必須傳入一個(gè)函數(shù)指針作為參數(shù),當(dāng)malloc申請(qǐng)內(nèi)存失敗時(shí)會(huì)去調(diào)用這個(gè)函數(shù)來(lái)釋放出足夠多的內(nèi)存空間。當(dāng)要申請(qǐng)的內(nèi)存大小超過(guò)128字節(jié)時(shí),調(diào)用默認(rèn)的malloc為其申請(qǐng)內(nèi)存。否則先查找列表中是否還有足夠的空間分配給它,若已沒(méi)有足夠的空間分配給它,則調(diào)用refill申請(qǐng)一塊大內(nèi)存。

然后是內(nèi)存釋放函數(shù)deallocate
            template <typename T>
            void deallocate(T* p, size_t n)
            {
                if(p == 0) return;
                if(n > MAX_BYTES)
                {
                    free(p);
                    return;
                }
                const int i = INDEX(ROUND_UP(n));
                reinterpret_cast<obj*>(p)->next = chunk_list[i];
                chunk_list[i] = reinterpret_cast<obj*>(p);
            }
值得注意的是在釋放時(shí)必須給出這塊內(nèi)存塊的大小。若這塊內(nèi)存大于128字節(jié)時(shí),調(diào)用默認(rèn)的free函數(shù)釋放掉這塊內(nèi)存。否則將其加到對(duì)應(yīng)的chunk_list列表內(nèi)。

然后是調(diào)整內(nèi)存塊大小函數(shù)reallocate
            template <typename T>
            T* reallocate(T* p, size_t old_size, size_t new_size, void(*h)(size_t))
            {
                if(old_size > MAX_BYTES && new_size > MAX_BYTES)
                {
                    return realloc(p, new_size);
                }
                if(ROUND_UP(old_size) == ROUND_UP(new_size)) return p;
                T* result = allocate<T>(new_size, h);
                const size_t copy_size = new_size > old_size ? old_size : new_size;
                memcpy(result, p, copy_size);
                deallocate<T>(p, old_size);
                return result;
            }
參數(shù)中必須給出這塊內(nèi)存的原始大小和要調(diào)整后的大小,同時(shí)也必須給出當(dāng)內(nèi)存不足時(shí)的釋放函數(shù)的指針。若舊內(nèi)存塊和新內(nèi)存塊的大小都大于128字節(jié)時(shí),調(diào)用默認(rèn)的realloc函數(shù)重新分配內(nèi)存。否則先按調(diào)整后的大小申請(qǐng)一塊內(nèi)存,并把原來(lái)的內(nèi)容拷貝過(guò)來(lái),最后釋放掉原來(lái)的內(nèi)存塊。這里并不建議使用這個(gè)函數(shù),而是手動(dòng)的去重新申請(qǐng)內(nèi)存并拷貝釋放。

然后來(lái)看4個(gè)非常簡(jiǎn)單的計(jì)算函數(shù)
            inline size_t ROUND_UP(size_t bytes)const
            {
                return (bytes + ALIGN - 1) & ~(ALIGN - 1);
            }

            inline size_t ROUND_DOWN(size_t bytes)const
            {
                return bytes & ~(ALIGN - 1);
            }

            inline int INDEX(size_t bytes)const
            {
                return (bytes + ALIGN - 1) / ALIGN - 1;
            }

            inline size_t obj_count(int i)const
            {
                size_t result = 0;
                obj* current = chunk_list[i];
                while(current)
                {
                    ++result;
                    current = current->next;
                }
                return result;
            }
前3個(gè)用于內(nèi)存對(duì)齊和計(jì)算索引,最后一個(gè)用于獲取一在空閑列表內(nèi)一個(gè)內(nèi)存塊的數(shù)量。

然后是refill函數(shù),用于在沒(méi)有空閑內(nèi)存塊時(shí)申請(qǐng)一塊大內(nèi)存塊
            template <typename T>
            T* refill(int i, void(*h)(size_t))
            {
                const int count = 20;
                const int preSize = (i + 1) * ALIGN;
                char* p = (char*)malloc(preSize * count);
                while(p == 0)
                {
                    h(preSize * count);
                    p = (char*)malloc(preSize * count);
                }
                block* pBlock = (block*)malloc(sizeof(block));
                while(pBlock == 0)
                {
                    h(sizeof(block));
                    pBlock = (block*)malloc(sizeof(block));
                }
                pBlock->data = p;
                pBlock->next = free_list;
                free_list = pBlock;
                obj* current = (obj*)(p + preSize);
                for(int j = 0; j < count - 1; ++j)
                {
                    current->next = chunk_list[i];
                    chunk_list[i] = current;
                    current = (obj*)((char*)current + preSize);
                }
                chunk_count += count - 1;
                rebalance();
                return reinterpret_cast<T*>(p);
            }
首先申請(qǐng)一個(gè)大內(nèi)存塊,然后將這塊申請(qǐng)到的內(nèi)存塊放入free_list鏈表內(nèi),最后組織起chunk_list中對(duì)應(yīng)內(nèi)存卡塊的鏈表,然后重新調(diào)整chunk_list列表,最后將申請(qǐng)到的內(nèi)存塊返回。

最后來(lái)看一下調(diào)整函數(shù)rebalance
            void rebalance()
            {
                for(int i = MAX_COUNT - 1; i > 0; --i)
                {
                    const size_t avge = chunk_count / MAX_COUNT;
                    size_t count = obj_count(i);
                    if(count > avge)
                    {
                        const int preSize = ROUND_DOWN((i + 1) * ALIGN / 2);
                        const int j = INDEX(preSize);
                        for(int k = count; k > avge; --k)
                        {
                            obj* chunk = chunk_list[i];
                            chunk_list[i] = chunk_list[i]->next;
                            if(i % 2 == 1)
                            {
                                chunk->next = (obj*)((char*)chunk + preSize);
                                chunk->next->next = chunk_list[j];
                                chunk_list[j] = chunk;
                            }
                            else
                            {
                                chunk->next = chunk_list[j];
                                chunk_list[j] = chunk;
                                obj* next = (obj*)((char*)chunk + preSize);
                                next->next = chunk_list[j + 1];
                                chunk_list[j + 1] = next;
                            }
                            ++chunk_count;
                        }
                    }
                }
            }
這里從后至前查看對(duì)應(yīng)內(nèi)存塊空閑鏈表的長(zhǎng)度,若超過(guò)平均數(shù)量,則將其切分為2塊較小的內(nèi)存塊放入對(duì)應(yīng)的鏈表內(nèi)。這樣做的好處是可以形成一個(gè)金字塔形的分布狀況,既越小的內(nèi)存塊大小擁有的節(jié)點(diǎn)數(shù)量越多,正如本文開(kāi)頭所說(shuō),使用內(nèi)存池是為了解決在申請(qǐng)小塊內(nèi)存時(shí)造成的內(nèi)存碎片。

至此,內(nèi)存池的講解已完成,完整的代碼請(qǐng)到http://qlanguage.codeplex.com下載
posted on 2012-07-14 18:40 lwch 閱讀(2445) 評(píng)論(1)  編輯 收藏 引用 所屬分類: STL

評(píng)論:
# re: 山寨STL實(shí)現(xiàn)之內(nèi)存池 2013-01-19 22:58 | eryar
Good,
Marked!  回復(fù)  更多評(píng)論
  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            性做久久久久久| 国产精品地址| 一区二区日韩欧美| 久久精品卡一| 欧美一区二区播放| 国产精品二区三区四区| 亚洲人成亚洲人成在线观看图片 | 亚洲日本黄色| 亚洲国产一区二区三区青草影视| 欧美中文字幕在线观看| 久久se精品一区二区| 国产精品网站视频| 亚洲午夜精品一区二区| 亚洲欧美在线免费| 国产精品日韩一区| 亚洲欧美在线一区二区| 欧美怡红院视频一区二区三区| 国产精品啊v在线| 亚洲午夜一区二区三区| 午夜视频久久久久久| 国产欧美日韩亚洲精品| 久久九九99视频| 亚洲电影免费观看高清完整版| 99精品久久久| 国产精品视频久久久| 欧美一区二区视频在线| 欧美aa在线视频| 一区二区不卡在线视频 午夜欧美不卡'| 欧美日韩的一区二区| 亚洲一区二区三区免费在线观看| 欧美在线亚洲综合一区| 激情综合色丁香一区二区| 另类欧美日韩国产在线| 亚洲精品国产精品国自产在线| 亚洲一级一区| 国语自产精品视频在线看一大j8| 美日韩精品免费| 99在线精品观看| 久久aⅴ国产欧美74aaa| 亚洲啪啪91| 国产精品久久久久久久7电影| 日韩一级裸体免费视频| 亚洲一区在线视频| 国产亚洲欧美一区在线观看| 午夜精品一区二区三区在线播放| 欧美1区2区视频| 一本色道久久综合狠狠躁的推荐| 欧美性猛交xxxx乱大交退制版 | 在线观看国产成人av片| 久久深夜福利免费观看| 亚洲国产精品一区二区www| 一本大道久久a久久精二百| 国产精品久久久久一区二区三区共| 亚洲免费一级电影| 国产精品劲爆视频| 久久精品免费电影| 亚洲啪啪91| 午夜亚洲福利在线老司机| 亚洲欧美视频在线观看视频| 亚洲免费大片| 欧美午夜无遮挡| 欧美一区二区免费视频| 亚洲丰满在线| 亚洲一区欧美一区| 国产亚洲免费的视频看| 免费日韩av电影| 亚洲一区二区精品在线| 麻豆精品精华液| 亚洲一区二区免费| 好吊视频一区二区三区四区| 欧美国产成人精品| 午夜精品成人在线| 亚洲国内自拍| 亚洲女同精品视频| 亚洲美女福利视频网站| 国产精品婷婷午夜在线观看| 久久综合影音| 亚洲女人天堂成人av在线| 牛牛影视久久网| 午夜欧美大片免费观看| 亚洲欧洲精品一区二区三区不卡 | 国产亚洲精品久久久久婷婷瑜伽 | 国产精品国产馆在线真实露脸| 欧美成人性网| 欧美在线播放视频| 日韩视频免费观看高清完整版| 国产精品一区二区久久久久| 玖玖视频精品| 亚洲欧美伊人| 亚洲精品日韩激情在线电影| 久久国产精品亚洲77777| 亚洲国产精品久久久久| 国产精品一区二区你懂得| 欧美精品一区二区三区视频| 久久九九国产精品| 亚洲自拍偷拍视频| 亚洲免费av网站| 亚洲高清在线观看| 久久久xxx| 性感少妇一区| 亚洲永久免费av| 亚洲精品一级| 亚洲国产毛片完整版| 国产精品www色诱视频| 欧美日韩一区二区高清| 欧美r片在线| 美日韩精品视频免费看| 久久福利精品| 午夜精品影院| 亚洲夜间福利| 一区二区日韩伦理片| 亚洲欧洲一区| 亚洲人成啪啪网站| 亚洲国产精品久久久| 欧美大片在线观看| 欧美一区三区二区在线观看| 99国产精品| 亚洲乱码国产乱码精品精| 最新国产成人在线观看| 精品成人一区二区| 国产一区二区三区久久久| 国产欧美一区二区精品忘忧草| 欧美亚洲成人精品| 亚洲欧美日韩中文播放| 欧美精品激情| 久久精品中文字幕一区| 亚洲欧美日韩在线一区| 亚洲视频一区在线| 亚洲天堂免费观看| 一区二区三区 在线观看视| 亚洲精品影院在线观看| 91久久精品日日躁夜夜躁国产| 欧美成人一区二区三区在线观看| 美女视频一区免费观看| 美国成人直播| 欧美华人在线视频| 亚洲激情啪啪| 夜夜狂射影院欧美极品| 亚洲国产精品va在线观看黑人| 欧美激情视频一区二区三区不卡| 亚洲黄色视屏| 日韩亚洲一区二区| 亚洲网站在线观看| 亚洲欧美日韩另类| 久久精品国产亚洲a| 榴莲视频成人在线观看| 欧美激情无毛| 国产精品你懂的| 韩日欧美一区二区| 亚洲精品自在久久| 亚洲专区免费| 久久久久一区二区| 亚洲高清视频中文字幕| 99精品视频免费观看视频| 欧美亚洲一区在线| 免费观看国产成人| 国产精品福利在线观看| 好吊妞**欧美| 日韩一二三在线视频播| 亚洲男人天堂2024| 另类专区欧美制服同性| 亚洲激情视频| 亚洲精品国偷自产在线99热| 9l国产精品久久久久麻豆| 午夜国产精品视频免费体验区| 久久综合狠狠| 国产精品wwwwww| 亚洲观看高清完整版在线观看| 夜夜嗨av一区二区三区中文字幕 | 欧美华人在线视频| 国产欧美日韩综合| 日韩一区二区免费高清| 欧美在线视频一区| 蜜臀a∨国产成人精品 | 亚洲卡通欧美制服中文| 欧美一激情一区二区三区| 免费国产一区二区| 亚洲视屏在线播放| 欧美91视频| 欧美视频第二页| 亚洲第一黄色网| 午夜国产一区| 亚洲国产女人aaa毛片在线| 亚洲欧美日韩国产精品| 欧美成人精品1314www| 国产精品日本一区二区| 亚洲高清在线观看| 欧美一区2区视频在线观看 | 欧美激情一二区| 国产精品亚洲欧美| 夜夜夜久久久| 免费亚洲一区二区| 亚洲欧美日韩精品久久久久| 欧美黑人多人双交| 尤物九九久久国产精品的特点 | 欧美日精品一区视频| 1024国产精品| 久久精品亚洲精品| 中文国产一区| 欧美在线影院在线视频|