1. 程式人生 > >swoole原始碼解析之swoole_buffer的建立過程

swoole原始碼解析之swoole_buffer的建立過程

swoole提供了一個swoole_buffer類(程式碼位於swoole_buffer.c中),讓PHP開發者可以像C一樣直接讀寫記憶體,提升程式的效能,又不用擔心記憶體越界。swoole_buffer會檢測offset,但是swoole_buffer提供的記憶體空間不是共享記憶體形式的,不可以在多個程序間共享,swoole_buffer提供了兩個屬性如下。

  • swoole_buffer->$length,當前資料的長度
  • swoole_buffer->$capacity,當前快取區的容量

建立一個記憶體物件。函式原型:

swoole_buffer->__construct(int $size = 128);

引數$size指定了緩衝區記憶體的初始尺寸。當申請的記憶體容量不夠時swoole底層會自動擴容。

下面我們看看其構造過程。

static PHP_METHOD(swoole_buffer, __construct)
{
    long size = SW_STRING_BUFFER_DEFAULT;
    //解析輸入引數,這裡輸入引數用來指定要申請的記憶體空間大小,如果使用者側不設定,預設取SW_STRING_BUFFER_DEFAULT,其值為128
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &size) == FAILURE)
    {
        RETURN_FALSE;
    }

    if (size < 1)//size有效性檢查
    {
        zend_throw_exception(swoole_exception_class_entry_ptr, "buffer size can't be less than 0.", SW_ERROR_INVALID_PARAMS TSRMLS_CC);
        RETURN_FALSE;
    }
    else if (size > SW_STRING_BUFFER_MAXLEN)//最大空間限制為SW_STRING_BUFFER_MAXLEN,其值為128M
    {
        zend_throw_exception_ex(swoole_exception_class_entry_ptr, errno TSRMLS_CC, "buffer size can't exceed %d", SW_STRING_BUFFER_MAXLEN);
        RETURN_FALSE;
    }

    swString *buffer = swString_new(size);//申請size大小的記憶體空間,其實現在下面分析
    if (buffer == NULL)
    {
        zend_throw_exception_ex(swoole_exception_class_entry_ptr, errno TSRMLS_CC, "malloc(%ld) failed.", size);
        RETURN_FALSE;
    }

    swoole_set_object(getThis(), buffer);//建立PHP側的物件swoole_buffer和swoole內部物件buffer的對應關係
    zend_update_property_long(swoole_buffer_class_entry_ptr, getThis(), ZEND_STRL("capacity"), size TSRMLS_CC);//設定swoole_buffer的capacity屬性,取值為size
    zend_update_property_long(swoole_buffer_class_entry_ptr, getThis(), ZEND_STRL("length"), 0 TSRMLS_CC);//設定swoole_buffer的length屬性,取值為0,即表示目前還沒使用這個空間
}
swString *swString_new(size_t size)
{
    swString *str = sw_malloc(sizeof(swString));//申請swString物件記憶體,大小為sizeof(swString)
    if (str == NULL)//申請失敗
    {
        swWarn("malloc[1] failed.");
        return NULL;
    }

    bzero(str, sizeof(swString));//空間初始化
    str->size = size;//設定size屬性
    str->str = sw_malloc(size);//申請str記憶體空間
    if (str->str == NULL)//申請失敗
    {
        swSysError("malloc[2](%ld) failed.", size);
        sw_free(str);
        return NULL;
    }
    return str;
}
#ifdef SW_USE_JEMALLOC //如果可以使用jemalloc
#include <jemalloc/jemalloc.h>
#define sw_malloc              je_malloc//sw_malloc通過je_malloc實現
#define sw_free                je_free
#define sw_calloc              je_calloc
#define sw_realloc             je_realloc
#else
#define sw_malloc              malloc//通過預設的malloc實現
#define sw_free                free
#define sw_calloc              calloc
#define sw_realloc             realloc
#endif