Redis分配內存的一些疑惑
以下部分只是作者的臆測,
還沒有的到證實,因為作者的C語言水平有限,還望有高手能夠出來指導,謝謝..
#define update_zmalloc_stat_alloc(__n) do { size_t _n = (__n); //重點在這裡 if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1)); if (zmalloc_thread_safe) { update_zmalloc_stat_add(_n); } else { used_memory += _n; } } while(0)
if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n(sizeof(long)-1));
它的意思是將申請的內存位元組數目對於sizeof(long)來向上取整,即總是取sizeof(long)的倍數.
解釋(機器字長)CPU在讀取內存的時候, 並不是按照一個位元組一個位元組的來讀取, 而是一次讀取一個`機器字`的長度. 例如 32 位的CPU一次讀取 32 bits的數據, 也就是 32 / 8 = 4 Bytes(4個位元組)的內存信息.zmalloc 中這樣來處理分配內存的大小, 是為了在為同一個數據分配的內存, 能夠在最少的 CPU 時鐘周期里讀取完成.疑惑2同樣是分配內存空間的代碼中, 每次分配內存的時候會在內存的起始位置加上 PREFIX_SIZE大小的內存, 並且存放的是此次`分配內存的大小`.
PREFIX_SIZE的定義如下:#ifdef HAVE_MALLOC_SIZE#define PREFIX_SIZE (0)#else#if defined(__sun) || defined(__sparc) || defined(__sparc__)#define PREFIX_SIZE (sizeof(long long))#else#define PREFIX_SIZE (sizeof(size_t))#endif#endif
不同的OS結構下面, 其值不一樣.
對於分配內存的時候, 多分配 `PREFIX_SIZE` 位元組的內存空間並且存儲此次分配內存空間的大小, 代碼如下:void *zmalloc(size_t size) { //這裡可見分內的時候, 會多分配 PREFIX_SIZE 位元組 void *ptr = malloc(size + PREFIX_SIZE); if(!ptr) zmalloc_oom_handler(size);#ifdef HAVE_MALLOC_SIZE //這裡表示 OS 會自己統計已分配內存的大小 update_zmalloc_stat_alloc(zmalloc_size(ptr)); return ptr;#else *((size_t*)ptr) = size; //轉換指針 ptr 的類型, 並且在指針開始的 PREFIX_SIZE 個位元組中賦值 size update_zmalloc_stat_alloc(size + PREFIX_SIZE); // 轉換指針 ptr 的類型為 char* , 操作指針偏移的時候, 便宜量保證只有一個位元組 // // 通過之前的代碼可以看見, 在申請內存的時候總是會多申請 PREFIX_SIZE 個位元組的空間, // 並且在這些空間裡面保存了申請內存空間的大小 size // //可見這裡返回的指針已經向右偏移了 PREFIX_SIZE 個位元組, 也就是實際的內存開始位置 return (char*)ptr + PREFIX_SIZE;#endif}
推薦閱讀:
※Linux 中的「大內存頁」(hugepage)是個什麼?
※從C++的RAII理解智能指針的思路(二)
※九. 內核的內存分配
※內核如何管理內存