新增zmalloc.h zmalloc.c部分注释

This commit is contained in:
zhuyijun 2021-11-07 20:11:42 +08:00
parent d43e1b37de
commit 28ae5daf6c
5 changed files with 141 additions and 29 deletions

View File

@ -109,7 +109,7 @@
(!defined(__clang__) || !defined(__APPLE__) || __apple_build_version__ > 4210057) && \
defined(__ATOMIC_RELAXED) && defined(__ATOMIC_SEQ_CST)
/* Implementation using __atomic macros. */
//原子操作 增加
#define atomicIncr(var,count) __atomic_add_fetch(&var,(count),__ATOMIC_RELAXED)
#define atomicGetIncr(var,oldvalue_var,count) do { \
oldvalue_var = __atomic_fetch_add(&var,(count),__ATOMIC_RELAXED); \

View File

@ -212,6 +212,21 @@ sds _sdsnewlen(const void *init, size_t initlen, int trymalloc) {
s[initlen] = '\0';
return s;
}
/*
* init initlen
* sds
*
*
* init
* initlen
*
*
* sds sdshdr sds
* NULL
*
*
* T = O(N)
*/
/**
* sds字符串 使s_malloc_usable创建内存空间
* @param init

View File

@ -41,10 +41,66 @@ extern const char *SDS_NOINIT;
#include <sys/types.h>
#include <stdarg.h>
#include <stdint.h>
/**
/*
* sds char *
*/
typedef char *sds;
/*
C ASCII
使 C
使(Redis\0Cluster\0) 使 C C
"Redis" "Cluster"
使 Redis 使
SDS API binary-safe SDS API SDS buf
SDS buf Redis
*/
/*
2-1 C SDS
C SDS
O(N) O(1)
API API
N N N N
使 <string.h> 使 <string.h>
*/
/*
2-2 SDS API
sdsnew C SDS O(N) N C
sdsempty SDS O(1)
sdsfree SDS O(1)
sdslen SDS 使 SDS len O(1)
sdsavail SDS 使 SDS free O(1)
sdsdup SDS copy O(N) N SDS
sdsclear SDS O(1)
sdscat C SDS O(N) N C
sdscatsds SDS SDS O(N) N SDS
sdscpy C SDS SDS O(N) N C
sdsgrowzero SDS O(N) N
sdsrange SDS O(N) N
sdstrim SDS C SDS
C O(M*N) M SDS N C
sdscmp SDS O(N) N SDS SDS
....
*/
/*
?
SDS SDS API SDS SDS
SDS SDS 使
使
SDS SDS len 1 MB len 使
SDS len free SDS len 13 13
使 SDS buf 13 + 13 + 1 = 27
SDS SDS 1 MB 1 MB 使 SDS
len 30 MB 1 MB 使 SDS buf 30 MB + 1 MB + 1 byte
Redis
SDS N N N sdscat
*/
/* Note: sdshdr5 is never used, we just access the flags byte directly.
* However is here to document the layout of type 5 SDS strings. */
@ -52,7 +108,7 @@ typedef char *sds;
// 这里的 '__attribute__ ((__packed__))' 要求编译器取消内存对齐优化,按照实际的占用字节数进行对齐
// string_size < 32
struct __attribute__ ((__packed__)) sdshdr5 {
/**
/*
* 5 3
*/
unsigned char flags; /* 3 lsb of type, and 5 msb of string length */

View File

@ -79,22 +79,24 @@ void zlibc_free(void *ptr) {
#define mallocx(size,flags) je_mallocx(size,flags)
#define dallocx(ptr,flags) je_dallocx(ptr,flags)
#endif
//宏函数 更新内存使用变量函数
#define update_zmalloc_stat_alloc(__n) atomicIncr(used_memory,(__n))
//宏函数
#define update_zmalloc_stat_free(__n) atomicDecr(used_memory,(__n))
static redisAtomic size_t used_memory = 0;
// 被 zmalloc_oom_handler 函数指针 所指向
static void zmalloc_default_oom(size_t size) {
//oom是out of memory内存不足的意思
fprintf(stderr, "zmalloc: Out of memory trying to allocate %zu bytes\n",
size);
fflush(stderr);
abort();
}
// 函数指针 调用zmalloc_default_oom
static void (*zmalloc_oom_handler)(size_t) = zmalloc_default_oom;
/**
* NULL则分配内存失败*usable设置为可用内存大小
* NULL则分配内存失败*usable设置为可用内存大小
* @param size
* @param usable
* @return
@ -103,11 +105,13 @@ static void (*zmalloc_oom_handler)(size_t) = zmalloc_default_oom;
* '*usable' is set to the usable size if non NULL. */
void *ztrymalloc_usable(size_t size, size_t *usable) {
ASSERT_NO_SIZE_OVERFLOW(size);
//申请内存
void *ptr = malloc(MALLOC_MIN_SIZE(size)+PREFIX_SIZE);
if (!ptr) return NULL;
#ifdef HAVE_MALLOC_SIZE
size = zmalloc_size(ptr);
//更新内存
update_zmalloc_stat_alloc(size);
if (usable) *usable = size;
return ptr;
@ -119,24 +123,28 @@ void *ztrymalloc_usable(size_t size, size_t *usable) {
#endif
}
/**
*
* OOM NULL
* @param size
* @return
*/
/* Allocate memory or panic */
void *zmalloc(size_t size) {
//尝试申请内存 返回如果为NULL则分配内存失败
void *ptr = ztrymalloc_usable(size, NULL);
// 如果申请失败 报OOM
if (!ptr) zmalloc_oom_handler(size);
return ptr;
}
//尝试申请内存 申请失败返回NULL 不报OOM异常
/* Try allocating memory, and return NULL if failed. */
void *ztrymalloc(size_t size) {
// 申请内存空间
void *ptr = ztrymalloc_usable(size, NULL);
return ptr;
}
/**
* NULL则分配内存失败 *usable
* NULL则分配内存失败 *usable
* OOM
* @param size
* @param usable
* @return
@ -152,6 +160,7 @@ void *zmalloc_usable(size_t size, size_t *usable) {
/* Allocation and free functions that bypass the thread cache
* and go straight to the allocator arena bins.
* Currently implemented only for jemalloc. Used for online defragmentation. */
// 只针对支持 jemalloc 绕过线程缓存直接分配内存
#ifdef HAVE_DEFRAG
void *zmalloc_no_tcache(size_t size) {
ASSERT_NO_SIZE_OVERFLOW(size);
@ -160,7 +169,7 @@ void *zmalloc_no_tcache(size_t size) {
update_zmalloc_stat_alloc(zmalloc_size(ptr));
return ptr;
}
// 只针对支持 jemalloc 绕过线程缓存 释放内存
void zfree_no_tcache(void *ptr) {
if (ptr == NULL) return;
update_zmalloc_stat_free(zmalloc_size(ptr));
@ -170,6 +179,7 @@ void zfree_no_tcache(void *ptr) {
/* Try allocating memory and zero it, and return NULL if failed.
* '*usable' is set to the usable size if non NULL. */
//审配内存 如果成功设置usable为分配的内存大小 反正返回NULL
void *ztrycalloc_usable(size_t size, size_t *usable) {
ASSERT_NO_SIZE_OVERFLOW(size);
void *ptr = calloc(1, MALLOC_MIN_SIZE(size)+PREFIX_SIZE);
@ -187,20 +197,21 @@ void *ztrycalloc_usable(size_t size, size_t *usable) {
return (char*)ptr+PREFIX_SIZE;
#endif
}
//申请内存并将其归0 申请失败返回NULL并报 OOM 异常
/* Allocate memory and zero it or panic */
void *zcalloc(size_t size) {
void *ptr = ztrycalloc_usable(size, NULL);
//报OOM异常
if (!ptr) zmalloc_oom_handler(size);
return ptr;
}
//尝试申请内存
/* Try allocating memory, and return NULL if failed. */
void *ztrycalloc(size_t size) {
void *ptr = ztrycalloc_usable(size, NULL);
return ptr;
}
//申请内存
/* Allocate memory or panic.
* '*usable' is set to the usable size if non NULL. */
void *zcalloc_usable(size_t size, size_t *usable) {
@ -208,7 +219,7 @@ void *zcalloc_usable(size_t size, size_t *usable) {
if (!ptr) zmalloc_oom_handler(size);
return ptr;
}
//尝试重新分配内存
/* Try reallocating memory, and return NULL if failed.
* '*usable' is set to the usable size if non NULL. */
void *ztryrealloc_usable(void *ptr, size_t size, size_t *usable) {
@ -221,6 +232,7 @@ void *ztryrealloc_usable(void *ptr, size_t size, size_t *usable) {
/* not allocating anything, just redirect to free. */
if (size == 0 && ptr != NULL) {
//不分配 并释放ptr
zfree(ptr);
if (usable) *usable = 0;
return NULL;
@ -231,6 +243,7 @@ void *ztryrealloc_usable(void *ptr, size_t size, size_t *usable) {
#ifdef HAVE_MALLOC_SIZE
oldsize = zmalloc_size(ptr);
//重新分配内存
newptr = realloc(ptr,size);
if (newptr == NULL) {
if (usable) *usable = 0;
@ -259,7 +272,7 @@ void *ztryrealloc_usable(void *ptr, size_t size, size_t *usable) {
#endif
}
/**
* 0
* 0 NULL OOM异常
* @param ptr
* @param size
* @return
@ -270,14 +283,19 @@ void *zrealloc(void *ptr, size_t size) {
if (!ptr && size != 0) zmalloc_oom_handler(size);
return ptr;
}
/**
* 0 NULL
* @param ptr
* @param size
* @return
*/
/* Try Reallocating memory, and return NULL if failed. */
void *ztryrealloc(void *ptr, size_t size) {
ptr = ztryrealloc_usable(ptr, size, NULL);
return ptr;
}
/**
* NULL则内存分配失败
* NULL则内存分配失败 OOM异常
* @param ptr
* @param size
* @param usable
@ -325,7 +343,11 @@ void zfree(void *ptr) {
free(realptr);
#endif
}
/**
* usable为释放内存的大小
* @param ptr
* @param usable
*/
/* Similar to zfree, '*usable' is set to the usable size being freed. */
void zfree_usable(void *ptr, size_t *usable) {
#ifndef HAVE_MALLOC_SIZE
@ -344,7 +366,7 @@ void zfree_usable(void *ptr, size_t *usable) {
free(realptr);
#endif
}
//字符串持久化存储函数函数,为字符串在堆内分配内存。
char *zstrdup(const char *s) {
size_t l = strlen(s)+1;
char *p = zmalloc(l);
@ -352,13 +374,13 @@ char *zstrdup(const char *s) {
memcpy(p,s,l);
return p;
}
//获取已经使用内存大小函数。
size_t zmalloc_used_memory(void) {
size_t um;
atomicGet(used_memory,um);
return um;
}
//设置内存异常时调用的函数。
void zmalloc_set_oom_handler(void (*oom_handler)(size_t)) {
zmalloc_oom_handler = oom_handler;
}
@ -377,8 +399,9 @@ void zmalloc_set_oom_handler(void (*oom_handler)(size_t)) {
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//获取进程可使用的所有内存大小。
size_t zmalloc_get_rss(void) {
//获取系统执行的配置信息 _SC_PAGESIZE
int page = sysconf(_SC_PAGESIZE);
size_t rss;
char buf[4096];
@ -404,7 +427,6 @@ size_t zmalloc_get_rss(void) {
x = strchr(p,' ');
if (!x) return 0;
*x = '\0';
rss = strtoll(p,NULL,10);
rss *= page;
return rss;
@ -501,7 +523,7 @@ size_t zmalloc_get_rss(void) {
#endif
#if defined(USE_JEMALLOC)
// 获取分配器的信息主要在使用jemalloc前提下使用获取jemalloc分配的信息
int zmalloc_get_allocator_info(size_t *allocated,
size_t *active,
size_t *resident) {
@ -523,11 +545,12 @@ int zmalloc_get_allocator_info(size_t *allocated,
je_mallctl("stats.allocated", allocated, &sz, NULL, 0);
return 1;
}
// 让 jemalloc 异步清除
void set_jemalloc_bg_thread(int enable) {
/* let jemalloc do purging asynchronously, required when there's no traffic
* after flushdb */
char val = !!enable;
// je_mallctl 设置 background_thread 变量地址&val 变量长度1
je_mallctl("background_thread", NULL, 0, &val, 1);
}
@ -536,6 +559,7 @@ int jemalloc_purge() {
char tmp[32];
unsigned narenas = 0;
size_t sz = sizeof(unsigned);
//查询arenas.narenas
if (!je_mallctl("arenas.narenas", &narenas, &sz, NULL, 0)) {
sprintf(tmp, "arena.%d.purge", narenas);
if (!je_mallctl(tmp, NULL, 0, NULL, 0))
@ -581,16 +605,18 @@ int jemalloc_purge() {
*
* Example: zmalloc_get_smap_bytes_by_field("Rss:",-1);
*/
//信息统计 使用/poc/self/smaps的统计信息
#if defined(HAVE_PROC_SMAPS)
size_t zmalloc_get_smap_bytes_by_field(char *field, long pid) {
char line[1024];
size_t bytes = 0;
int flen = strlen(field);
FILE *fp;
//如果为-1 报告的信息就是当前线程的
if (pid == -1) {
fp = fopen("/proc/self/smaps","r");
} else {
//否则通过查询pid线程信息
char filename[128];
snprintf(filename,sizeof(filename),"/proc/%ld/smaps",pid);
fp = fopen(filename,"r");

View File

@ -34,6 +34,9 @@
/* Double expansion needed for stringification of macro values. */
#define __xstr(s) __str(s)
#define __str(s) #s
/*
* TCMallocTCMalloc(Thread-Caching Malloc)glibc库的malloc实现一样的功能TCMalloc在效率和速度效率都比标准malloc高很多
*/
#if defined(USE_TCMALLOC)
#define ZMALLOC_LIB ("tcmalloc-" __xstr(TC_VERSION_MAJOR) "." __xstr(TC_VERSION_MINOR))
@ -45,16 +48,18 @@
#error "Newer version of tcmalloc required"
#endif
//检查是否定义了jemalloc库
#elif defined(USE_JEMALLOC)
#define ZMALLOC_LIB ("jemalloc-" __xstr(JEMALLOC_VERSION_MAJOR) "." __xstr(JEMALLOC_VERSION_MINOR) "." __xstr(JEMALLOC_VERSION_BUGFIX))
#include <jemalloc/jemalloc.h>
#if (JEMALLOC_VERSION_MAJOR == 2 && JEMALLOC_VERSION_MINOR >= 1) || (JEMALLOC_VERSION_MAJOR > 2)
#define HAVE_MALLOC_SIZE 1
//
#define zmalloc_size(p) je_malloc_usable_size(p)
#else
#error "Newer version of jemalloc required"
#endif
//检查是否是苹果系统
#elif defined(__APPLE__)
#include <malloc/malloc.h>
#define HAVE_MALLOC_SIZE 1
@ -95,13 +100,17 @@
#if defined(USE_JEMALLOC) && defined(JEMALLOC_FRAG_HINT)
#define HAVE_DEFRAG
#endif
//重写malloc函数申请内存
void *zmalloc(size_t size);
//重写calloc函数不再支持按块的成倍申请内部调用的是zmalloc
void *zcalloc(size_t size);
//重写内存扩展函数
void *zrealloc(void *ptr, size_t size);
void *ztrymalloc(size_t size);
void *ztrycalloc(size_t size);
void *ztryrealloc(void *ptr, size_t size);
//重写内存释放函数,释放时会更新已使用内存的值,如果在多线程下没有开启线程安全模式,可能会出现并发错误。
void zfree(void *ptr);
void *zmalloc_usable(size_t size, size_t *usable);
void *zcalloc_usable(size_t size, size_t *usable);
@ -110,9 +119,13 @@ void *ztrymalloc_usable(size_t size, size_t *usable);
void *ztrycalloc_usable(size_t size, size_t *usable);
void *ztryrealloc_usable(void *ptr, size_t size, size_t *usable);
void zfree_usable(void *ptr, size_t *usable);
//字符串持久化存储函数函数,为字符串在堆内分配内存。
char *zstrdup(const char *s);
//获取已经使用内存大小函数。
size_t zmalloc_used_memory(void);
//设置内存异常时调用的函数。
void zmalloc_set_oom_handler(void (*oom_handler)(size_t));
//获取进程可使用的所有内存大小。
size_t zmalloc_get_rss(void);
int zmalloc_get_allocator_info(size_t *allocated, size_t *active, size_t *resident);
void set_jemalloc_bg_thread(int enable);
@ -120,6 +133,7 @@ int jemalloc_purge();
size_t zmalloc_get_private_dirty(long pid);
size_t zmalloc_get_smap_bytes_by_field(char *field, long pid);
size_t zmalloc_get_memory_size(void);
//释放指针指向内存函数,用这个释放内存时,不会更新使用内存变量的值。
void zlibc_free(void *ptr);
#ifdef HAVE_DEFRAG
@ -128,6 +142,7 @@ void *zmalloc_no_tcache(size_t size);
#endif
#ifndef HAVE_MALLOC_SIZE
//获取内存块总题大小函数。
size_t zmalloc_size(void *ptr);
size_t zmalloc_usable_size(void *ptr);
#else