国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

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

stormzhang / 676人閱讀

摘要:前言中為了更好的進(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)存池:FixedPoolRingBufferMemoryGlobal

其中 MemoryGlobal 用于全局變量 SwooleG.memory_poolRingBuffer 用于 reactor 線程的緩沖區(qū),FixedPool 用于 swoole_table 共享內(nèi)存表。

swMemoryPool 內(nèi)存池?cái)?shù)據(jù)結(jié)構(gòu)

無(wú)論是哪種內(nèi)存池,它的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)都是 swMemoryPool:

typedef struct _swMemoryPool
{
    void *object;
    void* (*alloc)(struct _swMemoryPool *pool, uint32_t size);
    void (*free)(struct _swMemoryPool *pool, void *ptr);
    void (*destroy)(struct _swMemoryPool *pool);
} swMemoryPool;

可以看出來(lái), swMemoryPool 更加類似于接口,規(guī)定了內(nèi)存池需要定義的函數(shù)。

MemoryGlobal 內(nèi)存池實(shí)現(xiàn) MemoryGlobal 數(shù)據(jù)結(jié)構(gòu)

首先看一下 MemoryGlobal 的數(shù)據(jù)結(jié)構(gòu):

typedef struct _swMemoryGlobal_page
{
    struct _swMemoryGlobal_page *next;
    char memory[0];
} swMemoryGlobal_page;

typedef struct _swMemoryGlobal
{
    uint8_t shared;
    uint32_t pagesize;
    swLock lock;
    swMemoryGlobal_page *root_page;
    swMemoryGlobal_page *current_page;
    uint32_t current_offset;
} swMemoryGlobal;

可以很明顯的看出,MemoryGlobal 實(shí)際上就是一個(gè)單鏈表,root_page 是鏈表的頭,current_page 就是鏈表的尾,current_offset 指的是最后一個(gè)鏈表元素的偏移量。

比較特殊的是 MemoryGlobal 單鏈表內(nèi)存池的內(nèi)存只能增加不會(huì)減少。

MemoryGlobal 的創(chuàng)建
#define SW_MIN_PAGE_SIZE  4096

swMemoryPool* swMemoryGlobal_new(uint32_t pagesize, uint8_t shared)
{
    swMemoryGlobal gm, *gm_ptr;
    assert(pagesize >= SW_MIN_PAGE_SIZE);
    bzero(&gm, sizeof(swMemoryGlobal));

    gm.shared = shared;
    gm.pagesize = pagesize;

    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;

    gm_ptr = (swMemoryGlobal *) page->memory;
    gm.current_offset += sizeof(swMemoryGlobal);

    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;

    memcpy(gm_ptr, &gm, sizeof(gm));
    return allocator;
}

可以看到,每次申請(qǐng)創(chuàng)建 MemoryGlobal 內(nèi)存不得小于 2k

創(chuàng)建的 MemoryGlobalcurrent_offset 被初始化為 swMemoryGlobalswMemoryPool 的大小之和

返回的 allocator 類型是 swMemoryPool,其內(nèi)存結(jié)構(gòu)為:

swMemoryGlobal swMemoryPool memory

static swMemoryGlobal_page* swMemoryGlobal_new_page(swMemoryGlobal *gm)
{
    swMemoryGlobal_page *page = (gm->shared == 1) ? sw_shm_malloc(gm->pagesize) : sw_malloc(gm->pagesize);
    if (page == NULL)
    {
        return NULL;
    }
    bzero(page, gm->pagesize);
    page->next = NULL;

    if (gm->current_page != NULL)
    {
        gm->current_page->next = page;
    }

    gm->current_page = page;
    gm->current_offset = 0;

    return page;
}

鏈表元素的創(chuàng)建比較簡(jiǎn)單,就是申請(qǐng)內(nèi)存,初始化單鏈表的各個(gè)變量。

MemoryGlobal 內(nèi)存的申請(qǐng)
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))
    {
        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;
    }
    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);
    return mem;
}

申請(qǐng)內(nèi)存之前需要先將互斥鎖加鎖以防多個(gè)線程或多個(gè)進(jìn)程同時(shí)申請(qǐng)內(nèi)存,導(dǎo)致數(shù)據(jù)混亂。

如果申請(qǐng)的內(nèi)存大于單個(gè)鏈表元素的 pagesize,直接返回錯(cuò)誤。

如果當(dāng)前鏈表元素剩余的內(nèi)存不足,那么就會(huì)重新申請(qǐng)一個(gè)新的鏈表元素

設(shè)置 current_offset,解鎖互斥鎖,返回內(nèi)存地址。

MemoryGlobal 內(nèi)存的釋放與銷毀
static void swMemoryGlobal_free(swMemoryPool *pool, void *ptr)
{
    swWarn("swMemoryGlobal Allocator don"t need to release.");
}

static void swMemoryGlobal_destroy(swMemoryPool *poll)
{
    swMemoryGlobal *gm = poll->object;
    swMemoryGlobal_page *page = gm->root_page;
    swMemoryGlobal_page *next;

    do
    {
        next = page->next;
        sw_shm_free(page);
        page = next;
    } while (page);
}

MemoryGlobal 不需要進(jìn)行內(nèi)存的釋放

MemoryGlobal 的銷毀就是循環(huán)單鏈表,然后釋放內(nèi)存

RingBuffer 內(nèi)存池實(shí)現(xiàn) RingBuffer 的數(shù)據(jù)結(jié)構(gòu)

RingBuffer 類似于一個(gè)循環(huán)數(shù)組,每一次申請(qǐng)的一塊內(nèi)存在該數(shù)組中占據(jù)一個(gè)位置,這些內(nèi)存塊是可以不等長(zhǎng)的,因此每個(gè)內(nèi)存塊需要有一個(gè)記錄其長(zhǎng)度的變量。

typedef struct
{
    uint16_t lock;
    uint16_t index;
    uint32_t length;
    char data[0];
} swRingBuffer_item;

typedef struct
{
    uint8_t shared;
    uint8_t status;
    uint32_t size;
    uint32_t alloc_offset;
    uint32_t collect_offset;
    uint32_t alloc_count;
    sw_atomic_t free_count;
    void *memory;
} swRingBuffer;

swRingBuffer 中非常重要的成員變量是 alloc_offsetcollect_offsetalloc_offset 是當(dāng)前循環(huán)數(shù)組中的起始地址,collect_offset 代表當(dāng)前循環(huán)數(shù)組中可以被回收的內(nèi)存地址。

free_count 是當(dāng)前循環(huán)數(shù)組中可以被回收的個(gè)數(shù)。

status 為 0 代表循環(huán)數(shù)組當(dāng)前占用的內(nèi)存空間并沒(méi)有越過(guò)數(shù)組的結(jié)尾,也就是其地址是連續(xù)的,為 1 代表循環(huán)數(shù)組當(dāng)前占用的內(nèi)存空間一部分在循環(huán)數(shù)組的尾部,一部分在數(shù)組的頭部。

RingBuffer 的創(chuàng)建

RingBuffer 的創(chuàng)建類似于 MemoryGlobal

RingBuffer swMemoryPool memory
swMemoryPool *swRingBuffer_new(uint32_t size, uint8_t shared)
{
    void *mem = (shared == 1) ? sw_shm_malloc(size) : sw_malloc(size);
    if (mem == NULL)
    {
        swWarn("malloc(%d) failed.", size);
        return NULL;
    }

    swRingBuffer *object = mem;
    mem += sizeof(swRingBuffer);
    bzero(object, sizeof(swRingBuffer));

    object->size = (size - sizeof(swRingBuffer) - sizeof(swMemoryPool));
    object->shared = shared;

    swMemoryPool *pool = mem;
    mem += sizeof(swMemoryPool);

    pool->object = object;
    pool->destroy = swRingBuffer_destory;
    pool->free = swRingBuffer_free;
    pool->alloc = swRingBuffer_alloc;

    object->memory = mem;

    swDebug("memory: ptr=%p", mem);

    return pool;
}
RingBuffer 內(nèi)存的申請(qǐng)

free_count 大于 0,說(shuō)明此時(shí)數(shù)組中有待回收的內(nèi)存,需要進(jìn)行內(nèi)存回收

若當(dāng)前占用的內(nèi)存不是連續(xù)的,那么當(dāng)前內(nèi)存池剩余的容量就是 collect_offset - alloc_offset

若當(dāng)前占用的內(nèi)存是連續(xù)的,

而且數(shù)組當(dāng)前 collect_offset 距離尾部的內(nèi)存大于申請(qǐng)的內(nèi)存數(shù),那么剩余的容量就是 size - alloc_offset

數(shù)組當(dāng)前內(nèi)存位置距離尾部容量不足,那么就將當(dāng)前內(nèi)存到數(shù)組尾部打包成為一個(gè) swRingBuffer_item 數(shù)組元素,并標(biāo)志為待回收元素,設(shè)置 status 為 1,設(shè)置 alloc_offset 為數(shù)組首地址,此時(shí)剩余的容量就是 collect_offset 的地址

static void* swRingBuffer_alloc(swMemoryPool *pool, uint32_t size)
{
    assert(size > 0);

    swRingBuffer *object = pool->object;
    swRingBuffer_item *item;
    uint32_t capacity;

    uint32_t alloc_size = size + sizeof(swRingBuffer_item);

    if (object->free_count > 0)
    {
        swRingBuffer_collect(object);
    }

    if (object->status == 0)
    {
        if (object->alloc_offset + alloc_size >= (object->size - sizeof(swRingBuffer_item)))
        {
            uint32_t skip_n = object->size - object->alloc_offset;
            if (skip_n >= sizeof(swRingBuffer_item))
            {
                item = object->memory + object->alloc_offset;
                item->lock = 0;
                item->length = skip_n - sizeof(swRingBuffer_item);
                sw_atomic_t *free_count = &object->free_count;
                sw_atomic_fetch_add(free_count, 1);
            }
            object->alloc_offset = 0;
            object->status = 1;
            capacity = object->collect_offset - object->alloc_offset;
        }
        else
        {
            capacity = object->size - object->alloc_offset;
        }
    }
    else
    {
        capacity = object->collect_offset - object->alloc_offset;
    }

    if (capacity < alloc_size)
    {
        return NULL;
    }

    item = object->memory + object->alloc_offset;
    item->lock = 1;
    item->length = size;
    item->index = object->alloc_count;

    object->alloc_offset += alloc_size;
    object->alloc_count ++;

    swDebug("alloc: ptr=%p", (void * )((void * )item->data - object->memory));

    return item->data;
}
RingBuffer 內(nèi)存的回收

當(dāng) RingBufferfree_count 大于 0 的時(shí)候,就說(shuō)明當(dāng)前內(nèi)存池存在需要回收的元素,每次在申請(qǐng)新的內(nèi)存時(shí),都會(huì)調(diào)用這個(gè)函數(shù)來(lái)回收內(nèi)存。

回收內(nèi)存時(shí),本函數(shù)只會(huì)回收連續(xù)的多個(gè)空余的內(nèi)存元素,若多個(gè)待回收的內(nèi)存元素之間相互隔離,那么這些內(nèi)存元素不會(huì)被回收。

static void swRingBuffer_collect(swRingBuffer *object)
{
    swRingBuffer_item *item;
    sw_atomic_t *free_count = &object->free_count;

    int count = object->free_count;
    int i;
    uint32_t n_size;

    for (i = 0; i < count; i++)
    {
        item = object->memory + object->collect_offset;
        if (item->lock == 0)
        {
            n_size = item->length + sizeof(swRingBuffer_item);

            object->collect_offset += n_size;

            if (object->collect_offset + sizeof(swRingBuffer_item) >object->size || object->collect_offset >= object->size)
            {
                object->collect_offset = 0;
                object->status = 0;
            }
            sw_atomic_fetch_sub(free_count, 1);
        }
        else
        {
            break;
        }
    }
}
RingBuffer 內(nèi)存的釋放

內(nèi)存的釋放很簡(jiǎn)單,只需要設(shè)置 lock 為 0,并且增加 free_count 的數(shù)量即可:

static void swRingBuffer_free(swMemoryPool *pool, void *ptr)
{
    swRingBuffer *object = pool->object;
    swRingBuffer_item *item = ptr - sizeof(swRingBuffer_item);

    assert(ptr >= object->memory);
    assert(ptr <= object->memory + object->size);
    assert(item->lock == 1);

    if (item->lock != 1)
    {
        swDebug("invalid free: index=%d, ptr=%p", item->index,  (void * )((void * )item->data - object->memory));
    }
    else
    {
        item->lock = 0;
    }

    swDebug("free: ptr=%p", (void * )((void * )item->data - object->memory));

    sw_atomic_t *free_count = &object->free_count;
    sw_atomic_fetch_add(free_count, 1);
}
RingBuffer 內(nèi)存的銷毀
static void swRingBuffer_destory(swMemoryPool *pool)
{
    swRingBuffer *object = pool->object;
    if (object->shared)
    {
        sw_shm_free(object);
    }
    else
    {
        sw_free(object);
    }
}

值得注意的是,RingBuffer 除了原子鎖之外就沒(méi)有任何鎖了,在申請(qǐng)與釋放過(guò)程的代碼中也沒(méi)有看出來(lái)是線程安全的無(wú)鎖數(shù)據(jù)結(jié)構(gòu),個(gè)人認(rèn)為 RingBuffer 并非是線程安全/進(jìn)程安全的數(shù)據(jù)結(jié)構(gòu),因此利用這個(gè)內(nèi)存池申請(qǐng)共享內(nèi)存時(shí),需要自己進(jìn)行加鎖。

FixedPool 內(nèi)存池實(shí)現(xiàn) FixedPool 數(shù)據(jù)結(jié)構(gòu)

FixedPool 是隨機(jī)分配內(nèi)存池,將一整塊內(nèi)存空間切分成等大小的一個(gè)個(gè)小塊,每次分配其中的一個(gè)小塊作為要使用的內(nèi)存,這些小塊以雙向鏈表的形式存儲(chǔ)。

typedef struct _swFixedPool_slice
{
    uint8_t lock;
    struct _swFixedPool_slice *next;
    struct _swFixedPool_slice *pre;
    char data[0];

} swFixedPool_slice;

typedef struct _swFixedPool
{
    void *memory;
    size_t size;

    swFixedPool_slice *head;
    swFixedPool_slice *tail;

    /**
     * total memory size
     */
    uint32_t slice_num;

    /**
     * memory usage
     */
    uint32_t slice_use;

    /**
     * Fixed slice size, not include the memory used by swFixedPool_slice
     */
    uint32_t slice_size;

    /**
     * use shared memory
     */
    uint8_t shared;

} swFixedPool;
FixedPool 內(nèi)存池的創(chuàng)建

FixedPool 內(nèi)存池的創(chuàng)建有兩個(gè)函數(shù) swFixedPool_newswFixedPool_new2,其中 swFixedPool_new2 是利用已有的內(nèi)存基礎(chǔ)上來(lái)構(gòu)建內(nèi)存池,這個(gè)也是 table 共享內(nèi)存表創(chuàng)建的方法。

swMemoryPool* swFixedPool_new2(uint32_t slice_size, void *memory, size_t size)
{
    swFixedPool *object = memory;
    memory += sizeof(swFixedPool);
    bzero(object, sizeof(swFixedPool));

    object->slice_size = slice_size;
    object->size = size - sizeof(swMemoryPool) - sizeof(swFixedPool);
    object->slice_num = object->size / (slice_size + sizeof(swFixedPool_slice));

    swMemoryPool *pool = memory;
    memory += sizeof(swMemoryPool);
    bzero(pool, sizeof(swMemoryPool));

    pool->object = object;
    pool->alloc = swFixedPool_alloc;
    pool->free = swFixedPool_free;
    pool->destroy = swFixedPool_destroy;

    object->memory = memory;

    /**
     * init linked list
     */
    swFixedPool_init(object);

    return pool;
}

內(nèi)存池的創(chuàng)建和前兩個(gè)大同小異,只是這次多了 swFixedPool_init 這個(gè)構(gòu)建雙向鏈表的過(guò)程:

static void swFixedPool_init(swFixedPool *object)
{
    swFixedPool_slice *slice;
    void *cur = object->memory;
    void *max = object->memory + object->size;
    do
    {
        slice = (swFixedPool_slice *) cur;
        bzero(slice, sizeof(swFixedPool_slice));

        if (object->head != NULL)
        {
            object->head->pre = slice;
            slice->next = object->head;
        }
        else
        {
            object->tail = slice;
        }

        object->head = slice;
        cur += (sizeof(swFixedPool_slice) + object->slice_size);

        if (cur < max)
        {
            slice->pre = (swFixedPool_slice *) cur;
        }
        else
        {
            slice->pre = NULL;
            break;
        }

    } while (1);
}

可以看出來(lái),程序從內(nèi)存空間的首部開(kāi)始,每次初始化一個(gè) slice 大小的空間,并插入到鏈表的頭部,因此整個(gè)鏈表的內(nèi)存地址和 memory 的地址是相反的。

FixedPool 內(nèi)存池的申請(qǐng)
static void* swFixedPool_alloc(swMemoryPool *pool, uint32_t size)
{
    swFixedPool *object = pool->object;
    swFixedPool_slice *slice;

    slice = object->head;

    if (slice->lock == 0)
    {
        slice->lock = 1;
        object->slice_use ++;
        /**
         * move next slice to head (idle list)
         */
        object->head = slice->next;
        
        slice->next->pre = NULL;

        /*
         * move this slice to tail (busy list)
         */
        object->tail->next = slice;
        slice->next = NULL;
        slice->pre = object->tail;
        object->tail = slice;

        return slice->data;
    }
    else
    {
        return NULL;
    }
}

首先獲取內(nèi)存池鏈表首部的節(jié)點(diǎn),并判斷該節(jié)點(diǎn)是否被占用,如果被占用,說(shuō)明內(nèi)存池已滿,返回null(因?yàn)樗斜徽加玫墓?jié)點(diǎn)都會(huì)被放到尾部);如果未被占用,則將該節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)移到首部,并將該節(jié)點(diǎn)移動(dòng)到尾部,標(biāo)記該節(jié)點(diǎn)為占用狀態(tài),返回該節(jié)點(diǎn)的數(shù)據(jù)域。

FixedPool 內(nèi)存池的釋放
static void swFixedPool_free(swMemoryPool *pool, void *ptr)
{
    swFixedPool *object = pool->object;
    swFixedPool_slice *slice;

    assert(ptr > object->memory && ptr < object->memory + object->size);

    slice = ptr - sizeof(swFixedPool_slice);

    if (slice->lock)
    {
        object->slice_use--;
    }

    slice->lock = 0;

    //list head, AB
    if (slice->pre == NULL)
    {
        return;
    }
    //list tail, DE
    if (slice->next == NULL)
    {
        slice->pre->next = NULL;
        object->tail = slice->pre;
    }
    //middle BCD
    else
    {
        slice->pre->next = slice->next;
        slice->next->pre = slice->pre;
    }

    slice->pre = NULL;
    slice->next = object->head;
    object->head->pre = slice;
    object->head = slice;
}

首先通過(guò)移動(dòng) ptr 指針獲得 slice 對(duì)象,并將占用標(biāo)記 lock 置為 0。如果該節(jié)點(diǎn)為頭節(jié)點(diǎn),則直接返回。如果不是頭節(jié)點(diǎn),則將該節(jié)點(diǎn)移動(dòng)到鏈表頭部。

FixedPool 內(nèi)存池的銷毀
static void swFixedPool_destroy(swMemoryPool *pool)
{
    swFixedPool *object = pool->object;
    if (object->shared)
    {
        sw_shm_free(object);
    }
    else
    {
        sw_free(object);
    }
}

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/29222.html

相關(guān)文章

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

    摘要:如果互斥鎖的持有者死亡了,或者持有這樣的互斥鎖的進(jìn)程了互斥鎖所在的共享內(nèi)存或者持有這樣的互斥鎖的進(jìn)程執(zhí)行了調(diào)用,則會(huì)解除鎖定該互斥鎖。互斥鎖的下一個(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
  • swoolememoryGlobal內(nèi)存分析

    摘要:內(nèi)存池的作用直接使用系統(tǒng)調(diào)用會(huì)有如下弊端頻繁分配內(nèi)存時(shí)會(huì)產(chǎn)生大量?jī)?nèi)存碎片頻繁分配內(nèi)存增加系統(tǒng)調(diào)用開(kāi)銷容易造成內(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)用開(kāi)銷 容易造成內(nèi)存泄漏 ...

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

    摘要:前言我們知道,由于沒(méi)有多線程模型,所以更多的使用多進(jìn)程模型,因此代碼相對(duì)來(lái)說(shuō)更加簡(jiǎn)潔,減少了各種線程鎖的阻塞與同步,但是也帶來(lái)了新的問(wèn)題數(shù)據(jù)同步。相比多線程之前可以直接共享進(jìn)程的內(nèi)存,進(jìn)程之間數(shù)據(jù)的相互同步依賴于共享內(nèi)存。 前言 我們知道,由于 PHP 沒(méi)有多線程模型,所以 swoole 更多的使用多進(jìn)程模型,因此代碼相對(duì)來(lái)說(shuō)更加簡(jiǎn)潔,減少了各種線程鎖的阻塞與同步,但是也帶來(lái)了新的問(wèn)題...

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

    摘要:的數(shù)據(jù)結(jié)構(gòu)數(shù)據(jù)結(jié)構(gòu)中是鏈表元素的個(gè)數(shù),是緩沖區(qū)創(chuàng)建時(shí),鏈表元素約定的大小實(shí)際大小不一定是這個(gè)值,是實(shí)際上緩沖區(qū)占用的內(nèi)存總大小。中的有三種,分別應(yīng)用于緩存數(shù)據(jù)發(fā)送文件提醒連接關(guān)閉三種情景。指的是元素的內(nèi)存大小。 前言 swoole 中數(shù)據(jù)的接受與發(fā)送(例如 reactor 線程接受客戶端消息、發(fā)送給客戶端的消息、接受到的來(lái)自 worker 的消息、要發(fā)送給 worker 的消息等等)都...

    fyber 評(píng)論0 收藏0
  • Swoole 源碼分析——基礎(chǔ)模塊 Channel 隊(duì)列

    摘要:前言內(nèi)存數(shù)據(jù)結(jié)構(gòu),類似于的通道,底層基于共享內(nèi)存互斥鎖實(shí)現(xiàn),可實(shí)現(xiàn)用戶態(tài)的高性能內(nèi)存隊(duì)列。是當(dāng)前隊(duì)列占用的內(nèi)存大小,用來(lái)指定是否使用共享內(nèi)存是否使用鎖是否使用通知。 前言 內(nèi)存數(shù)據(jù)結(jié)構(gòu) Channel,類似于 Go 的 chan 通道,底層基于 共享內(nèi)存 + Mutex 互斥鎖實(shí)現(xiàn),可實(shí)現(xiàn)用戶態(tài)的高性能內(nèi)存隊(duì)列。Channel 可用于多進(jìn)程環(huán)境下,底層在讀取寫(xiě)入時(shí)會(huì)自動(dòng)加鎖,應(yīng)用層不需...

    txgcwm 評(píng)論0 收藏0

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

0條評(píng)論

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