亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

swoole之memoryGlobal內(nèi)存池分析

guyan0319 / 2188人閱讀

摘要:內(nèi)存池的作用直接使用系統(tǒng)調(diào)用會(huì)有如下弊端頻繁分配內(nèi)存時(shí)會(huì)產(chǎn)生大量?jī)?nèi)存碎片頻繁分配內(nèi)存增加系統(tǒng)調(diào)用開銷容易造成內(nèi)存泄漏內(nèi)存池是預(yù)先申請(qǐng)一定數(shù)量的,大小相等的內(nèi)存塊作為預(yù)備使用當(dāng)需要時(shí)向內(nèi)存池分出一部分內(nèi)存,若內(nèi)存塊不夠使用時(shí)再向系統(tǒng)申請(qǐng)新的內(nèi)

內(nèi)存池的作用:

直接使用系統(tǒng)調(diào)用malloc會(huì)有如下弊端:

頻繁分配內(nèi)存時(shí)會(huì)產(chǎn)生大量?jī)?nèi)存碎片

頻繁分配內(nèi)存增加系統(tǒng)調(diào)用開銷

容易造成內(nèi)存泄漏

內(nèi)存池是預(yù)先申請(qǐng)一定數(shù)量的,大小相等的內(nèi)存塊作為預(yù)備使用;當(dāng)需要時(shí)向內(nèi)存池分出一部分內(nèi)存,若內(nèi)存塊不夠使用時(shí)再向系統(tǒng)申請(qǐng)新的內(nèi)存塊,下面就swoole的swMemoryGlobal內(nèi)存池作為分析例子
swoole swMemoryPool 數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)

swMemoryGlobal是swoole內(nèi)存池實(shí)現(xiàn)一種方式,學(xué)習(xí)內(nèi)存池主要是要掌握其數(shù)據(jù)結(jié)構(gòu)的設(shè)計(jì),memoryGlobal實(shí)現(xiàn)如下:

// src/memory/MemoryGlobal.c
typedef struct _swMemoryPool
{
    void *object;                                               // 指向swMemoryGlobal指針
    void* (*alloc)(struct _swMemoryPool *pool, uint32_t size);  // 分配內(nèi)存函數(shù)指針
    void (*free)(struct _swMemoryPool *pool, void *ptr);        // 是否內(nèi)存函數(shù)指針
    void (*destroy)(struct _swMemoryPool *pool);                // 銷毀內(nèi)存函數(shù)指針
} swMemoryPool;

typedef struct _swMemoryGlobal
{
    uint8_t shared;                      
    uint32_t pagesize;                    // 指定每個(gè)swMemoryGlobal_page需要申請(qǐng)內(nèi)存大小
    swLock lock;                          // 互斥鎖
    swMemoryGlobal_page *root_page;       // 指向第一個(gè)swMemoryGlobal_page指針,有頭指針可以銷毀內(nèi)存池
    swMemoryGlobal_page *current_page;    // 指向當(dāng)前swMemoryGlobal_page指針
    uint32_t current_offset;
} swMemoryGlobal;

typedef struct _swMemoryGlobal_page
{
    struct _swMemoryGlobal_page *next;    // 指向下一個(gè)節(jié)點(diǎn)
    char memory[0];                       // 這是一個(gè)柔性數(shù)組,用于記錄申請(qǐng)內(nèi)存后的內(nèi)存地址
} swMemoryGlobal_page;

這三者之間的關(guān)系如下:

swMemoryPool

swMemoryPool可以看做是一個(gè)類,它提過(guò)了alloc,free,destory方法,以及object屬性,object實(shí)際上是指向swMemoryGlobal的指針,而alloc,free,destory
則是對(duì)object操作,即通過(guò)alloc,free,destory操作swMemoryGlobal上的內(nèi)容,例如:

// src/core/base.c
//init global shared memory
SwooleG.memory_pool = swMemoryGlobal_new(SW_GLOBAL_MEMORY_PAGESIZE, 1);
SwooleGS = SwooleG.memory_pool->alloc(SwooleG.memory_pool, sizeof(SwooleGS_t));

以上代碼是分配sizeof(SwooleGS_t)大小內(nèi)存

swMemoryGlobal

swMemoryGlobal維護(hù)著一個(gè)鏈表,每個(gè)節(jié)點(diǎn)即swMemoryGlobal_page,root_page指向第一個(gè)節(jié)點(diǎn),current_page指向當(dāng)前節(jié)點(diǎn),pagesize指為一個(gè)節(jié)點(diǎn)申請(qǐng)
內(nèi)存大小,current_offset則表示一個(gè)節(jié)點(diǎn)已被使用內(nèi)存

swMemoryGlobal_page

swoole根據(jù)swMemoryGlobal.pagesize申請(qǐng)指定大小的內(nèi)存,如下:

// src/memory/MemoryGlobal.c
swMemoryGlobal_page *page = swMemoryGlobal_new_page(&gm);

上面說(shuō)過(guò)swMemoryGlobal_page是一個(gè)鏈表節(jié)點(diǎn),這里需要說(shuō)明的是第一個(gè)節(jié)點(diǎn),第一個(gè)節(jié)點(diǎn)的current_offset為sizeof(swMemoryGlobal) + sizeof(swMemoryPool);
而并非為0;如下代碼,當(dāng)為第一個(gè)swMemoryGlobal_page申請(qǐng)內(nèi)存后,立馬就為swMemoryPool和swMemoryGlobal分配內(nèi)存

// src/memory/MemoryGlobal.c
gm.pagesize = pagesize;
// 系統(tǒng)申請(qǐng)一個(gè)pagesize大小內(nèi)存
swMemoryGlobal_page *page = swMemoryGlobal_new_page(&gm);
if (page == NULL)
{
    return NULL;
}
if (swMutex_create(&gm.lock, shared) < 0)
{
    return NULL;
}
    
gm.root_page = page;

// page->memory為空閑內(nèi)存
gm_ptr = (swMemoryGlobal *) page->memory;
gm.current_offset += sizeof(swMemoryGlobal);

// swMemoryPool指向空閑內(nèi)存偏移地址,占用sizeof(swMemoryPool)內(nèi)存
swMemoryPool *allocator = (swMemoryPool *) (page->memory + gm.current_offset);
gm.current_offset += sizeof(swMemoryPool);

allocator->object = gm_ptr;
allocator->alloc = swMemoryGlobal_alloc;
allocator->destroy = swMemoryGlobal_destroy;
allocator->free = swMemoryGlobal_free;

// 將gm寫入到gm_ptr,即空閑內(nèi)存前sizeof(gm)用于swMemoryGlobal
memcpy(gm_ptr, &gm, sizeof(gm));
分配內(nèi)存

分配內(nèi)存由swMemoryGlobal_alloc方法執(zhí)行;該方法為swMemoryPool一個(gè)函數(shù)指針,如下

allocator->alloc = swMemoryGlobal_alloc;        // 分配方法
// src/core/base.c
//init global shared memory
SwooleG.memory_pool = swMemoryGlobal_new(SW_GLOBAL_MEMORY_PAGESIZE, 1);
SwooleGS = SwooleG.memory_pool->alloc(SwooleG.memory_pool, sizeof(SwooleGS_t));

// src/memory/MemoryGlobal.c
static void *swMemoryGlobal_alloc(swMemoryPool *pool, uint32_t size)
{
    swMemoryGlobal *gm = pool->object;
    gm->lock.lock(&gm->lock);
    if (size > gm->pagesize - sizeof(swMemoryGlobal_page)) // sizeof(swMemoryGlobal_page)為swMemoryGlobal_page類型的指針大小
    {
        swWarn("failed to alloc %d bytes, exceed the maximum size[%d].", size, gm->pagesize - (int) sizeof(swMemoryGlobal_page));
        gm->lock.unlock(&gm->lock);
        return NULL;
    }
    // 如果一個(gè)節(jié)點(diǎn)不夠分配內(nèi)存,則重新申請(qǐng)一個(gè)新節(jié)點(diǎn),并設(shè)置當(dāng)前節(jié)點(diǎn)current_page為新節(jié)點(diǎn)
    if (gm->current_offset + size > gm->pagesize - sizeof(swMemoryGlobal_page))
    {
        swMemoryGlobal_page *page = swMemoryGlobal_new_page(gm);
        if (page == NULL)
        {
            swWarn("swMemoryGlobal_alloc alloc memory error.");
            gm->lock.unlock(&gm->lock);
            return NULL;
        }
        gm->current_page = page;
    }
    void *mem = gm->current_page->memory + gm->current_offset;
    gm->current_offset += size;
    gm->lock.unlock(&gm->lock);
    
    // 結(jié)果返回空閑內(nèi)存的偏移地址
    return mem;
}
柔性數(shù)組

柔性數(shù)組(0長(zhǎng)度數(shù)組)作用: 為了滿足需要變長(zhǎng)度的結(jié)構(gòu)體(結(jié)構(gòu)體是可變長(zhǎng)的)

數(shù)組名不占用空間,分配的內(nèi)存是連續(xù)的

不會(huì)像定長(zhǎng)數(shù)組一樣浪費(fèi)空間

不會(huì)像指針一樣需要分別分配內(nèi)存,分別釋放內(nèi)存

定長(zhǎng)數(shù)組使用方便, 但是卻浪費(fèi)空間, 指針形式只多使用了一個(gè)指針的空間, 不會(huì)造成

我的筆記
柔性數(shù)組參考

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/29521.html

相關(guān)文章

  • Swoole 源碼分析——內(nèi)存模塊內(nèi)存

    摘要:前言中為了更好的進(jìn)行內(nèi)存管理,減少頻繁分配釋放內(nèi)存空間造成的損耗和內(nèi)存碎片,程序設(shè)計(jì)并實(shí)現(xiàn)了三種不同功能的內(nèi)存池,和。比較特殊的是單鏈表內(nèi)存池的內(nèi)存只能增加不會(huì)減少。 前言 Swoole 中為了更好的進(jìn)行內(nèi)存管理,減少頻繁分配釋放內(nèi)存空間造成的損耗和內(nèi)存碎片,程序設(shè)計(jì)并實(shí)現(xiàn)了三種不同功能的內(nèi)存池:FixedPool,RingBuffer 和 MemoryGlobal。 其中 Memor...

    stormzhang 評(píng)論0 收藏0
  • Swoole 源碼分析——內(nèi)存模塊共享內(nèi)存swoole_table

    摘要:如果互斥鎖的持有者死亡了,或者持有這樣的互斥鎖的進(jìn)程了互斥鎖所在的共享內(nèi)存或者持有這樣的互斥鎖的進(jìn)程執(zhí)行了調(diào)用,則會(huì)解除鎖定該互斥鎖?;コ怄i的下一個(gè)持有者將獲取該互斥鎖并返回錯(cuò)誤。 前言 swoole_table 一個(gè)基于共享內(nèi)存和鎖實(shí)現(xiàn)的超高性能,并發(fā)數(shù)據(jù)結(jié)構(gòu)。用于解決多進(jìn)程/多線程數(shù)據(jù)共享和同步加鎖問(wèn)題。 swoole_table 的數(shù)據(jù)結(jié)構(gòu) swoole_table 實(shí)際上...

    Invoker 評(píng)論0 收藏0
  • SMProxy,讓你的項(xiàng)目數(shù)據(jù)庫(kù)操作快三倍!

    摘要:一個(gè)基于協(xié)議,開發(fā)的數(shù)據(jù)庫(kù)連接池。也可以通過(guò)其自身的管理機(jī)制來(lái)監(jiān)視數(shù)據(jù)庫(kù)連接的數(shù)量使用情況等。超出最大連接數(shù)會(huì)采用協(xié)程掛起,等到有連接關(guān)閉再恢復(fù)協(xié)程繼續(xù)操作。 SMProxy GITHUB:https://github.com/louislivi/... Swoole MySQL Proxy 一個(gè)基于 MySQL 協(xié)議,Swoole 開發(fā)的MySQL數(shù)據(jù)庫(kù)連接池。 原理 將數(shù)據(jù)庫(kù)連接作...

    MartinHan 評(píng)論0 收藏0
  • Swoole 源碼分析——Server模塊Start

    摘要:是緩存區(qū)高水位線,達(dá)到了說(shuō)明緩沖區(qū)即將滿了創(chuàng)建線程函數(shù)用于將監(jiān)控的存放于中向中添加監(jiān)聽的文件描述符等待所有的線程開啟事件循環(huán)利用創(chuàng)建線程,線程啟動(dòng)函數(shù)是保存監(jiān)聽本函數(shù)將用于監(jiān)聽的存放到當(dāng)中,并設(shè)置相應(yīng)的屬性 Server 的啟動(dòng) 在 server 啟動(dòng)之前,swoole 首先要調(diào)用 php_swoole_register_callback 將 PHP 的回調(diào)函數(shù)注冊(cè)到 server...

    3fuyu 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<