zmalloc是什么

zmalloc是redis内存分配的基本操作,相当于包了一层malloc的操作,分配出来的内存不只是裸露的

API

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

void *zmalloc(size_t size);

void *zcalloc(size_t size);

void *zrealloc(void *ptr, size_t size);

void zfree(void *ptr);

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);

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);

内存分配zmalloc,zcalloc

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

void *zmalloc(size_t size) {

    void *ptr = malloc(size+PREFIX_SIZE);



    if (!ptr) zmalloc_oom_handler(size);

#ifdef HAVE_MALLOC_SIZE

    update_zmalloc_stat_alloc(zmalloc_size(ptr));

    return ptr;

#else

    *((size_t*)ptr) = size;

    update_zmalloc_stat_alloc(size+PREFIX_SIZE);

    return (char*)ptr+PREFIX_SIZE;

#endif

}

在zmalloc的内存分配中,会多分配PREFIX_SIZE(sizeof(size_t))个字节,多分配的是用来存储分配的字节数大小的。zcalloc其实和zmalloc做的事情差不多的,不作太多的赘余。

内存再分配 zrealloc

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

void *zrealloc(void *ptr, size_t size) {

#ifndef HAVE_MALLOC_SIZE

    void *realptr;

#endif

    size_t oldsize;

    void *newptr;



    if (size == 0 && ptr != NULL) {

        zfree(ptr);

        return NULL;

    }

    if (ptr == NULL) return zmalloc(size);

#ifdef HAVE_MALLOC_SIZE

    oldsize = zmalloc_size(ptr);

    newptr = realloc(ptr,size);

    if (!newptr) zmalloc_oom_handler(size);



    update_zmalloc_stat_free(oldsize);

    update_zmalloc_stat_alloc(zmalloc_size(newptr));

    return newptr;

#else

    realptr = (char*)ptr-PREFIX_SIZE;

    oldsize = *((size_t*)realptr);

    newptr = realloc(realptr,size+PREFIX_SIZE);

    if (!newptr) zmalloc_oom_handler(size);



    *((size_t*)newptr) = size;

    update_zmalloc_stat_free(oldsize+PREFIX_SIZE);

    update_zmalloc_stat_alloc(size+PREFIX_SIZE);

    return (char*)newptr+PREFIX_SIZE;

#endif

}

在已申请的内存不够用时,需要扩大或者缩小内存的时候使用,注意一个细节,真正被分配的空间的开头是指向存储申请空间大小的地址的,所以,需要在ptr-PREFIX_SIZE才是真实被申请的空间的开头地址。

内存释放 zfree

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

void zfree(void *ptr) {

#ifndef HAVE_MALLOC_SIZE

    void *realptr;

    size_t oldsize;

#endif



    if (ptr == NULL) return;

#ifdef HAVE_MALLOC_SIZE

    update_zmalloc_stat_free(zmalloc_size(ptr));

    free(ptr);

#else

    realptr = (char*)ptr-PREFIX_SIZE;

    oldsize = *((size_t*)realptr);

    update_zmalloc_stat_free(oldsize+PREFIX_SIZE);

    free(realptr);

#endif

}

和zrealloc类型,需要注意一下真实申请的内存空间的开头地址的计算

内存拷贝 zstrdup

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15

char *zstrdup(const char *s) {

    size_t l = strlen(s)+1;

    char *p = zmalloc(l);



    memcpy(p,s,l);

    return p;

}