Redis source code interpretation of memory management ———— Zmalloc file

Source: Internet
Author: User

This article mainly records I am looking at the Redis source code of some understanding and ideas. Due to limited skill, there is definitely a malfunction, so. I hope the master gives a correction.

The first article is a memory-related introduction. Because I like to look at some components first, then look at the overall process.

Let's start with the code.

Header file

Primarily provides basic memory allocation and release capabilities

void *zmalloc (size_t size);//primary provides memory allocation and release of the underlying function 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_enable_thread_safeness ( void); void Zmalloc_set_oom_handler (void (*oom_handler) (size_t)); float zmalloc_get_fragmentation_ratio (void); size_ T zmalloc_get_rss (void); size_t zmalloc_get_private_dirty (void); void Zlibc_free (void *ptr); #ifndef have_malloc_ sizesize_t zmalloc_size (void *ptr); #endif

0. Preface

In this code we can see the Have_atomic macro definition, what is the function of it.

This file mainly provides the management of Tcmalloc and Jemalloc memory.

Tcmalloc is part of Google Perftool. Unlike a typical memory pool, which deals directly with the OS, the OS recycles when memory is idle (the STL memory pool is not recycled), and at the same time uses TLS (thread local storage) to manage the pool of memory, avoiding the need to synchronize the allocated memory within a thread.


Jemalloc and Tcmalloc are similar, the author Jason Evans is free BSD developer, performance and usage is not comparable with Tcmalloc.

Tcmalloc is more convenient to integrate with Google Perftool for performance evaluation.



Zmalloc primarily provides encapsulation of the malloc function, assuming that the malloc function is glibc, then the allocated memory is the length + memory to be allocated. Then put the head into the size

1. Request Memory

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}

Update_zmalloc_stat_alloc (Zmalloc_size (PTR)); is to align its own memory first, assuming that long is a 4-bit aligned to an integer multiple of 4. Then record the size of the memory into a global variable
For example, the following code
#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)
Memory has many different ways of doing it, and he is also very interesting.

The use of long can be either 64 machine or 32-bit machine. Assume that a mutually exclusive lock is used in a multithreaded situation.

Assuming that no macro have_malloc_size is defined, it is four bytes memory in front of the memory. Finally, the start address of the memory is returned.
Similarly

void *zcalloc (size_t size)
This method encapsulates the function of the Calloc function.
2. Request Memory again
Code such as the following
void *zrealloc (void *ptr, size_t size) {#ifndef have_malloc_size    void *realptr; #endif    size_t oldsize;    void *newptr;    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);    Update_zmalloc_stat_alloc (size);    Return (char*) newptr+prefix_size; #endif}

The method is to request memory of the specified size again for a specified amount of memory. The address has not changed.



3. Freeing up memory

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}

4. Copy memory, encapsulates the memcpy function
Char *zstrdup (const char *s) {    size_t L = strlen (s) +1;    Char *p = Zmalloc (l);    memcpy (p,s,l);    return p;}

5 getting the RSS physical memory valueBy looking at the 23rd line of the process's/proc/pid/stat file.
size_t Zmalloc_get_rss (void) {    int page = sysconf (_sc_pagesize);    size_t RSS;    Char buf[4096];    Char filename[256];    int fd, Count;    Char *p, *x;    snprintf (filename,256, "/proc/%d/stat", Getpid ());    if (fd = open (filename,o_rdonly)) = =-1) return 0;    if (read (fd,buf,4096) <= 0) {        close (FD);        return 0;    }    Close (FD);    p = buf;    Count = 23; /* RSS is the 24th field In/proc/<pid>/stat *    /while (P && count--) {        p = strchr (P, ');        if (p) p++;    }    if (!p) return 0;    x = STRCHR (P, ');    if (!x) return 0;    *x = ' + ';    rss = Strtoll (p,null,10);    RSS *= page;    return RSS;}

6. Memory Utilization
/* fragmentation = rss/allocated-bytes */float zmalloc_get_fragmentation_ratio (void) {    return (float) zmalloc_get_ RSS ()/zmalloc_used_memory ();}

7. Atomic additions under multi-threading

#ifdef have_atomic#define Update_zmalloc_stat_add (__n) __sync_add_and_fetch (&used_memory, (__n)) #define Update_ Zmalloc_stat_sub (__n) __sync_sub_and_fetch (&used_memory, (__n)) #else # define UPDATE_ZMALLOC_STAT_ADD (__n) do {     Pthread_mutex_lock (&used_memory_mutex);     Used_memory + = (__n);     Pthread_mutex_unlock (&used_memory_mutex); } while (0) #define UPDATE_ZMALLOC_STAT_SUB (__n) do {     pthread_mutex_lock (&used_memory_mutex);     Used_memory-= (__n);     Pthread_mutex_unlock (&used_memory_mutex); } while (0) #endif


The memory management of the Redis memory using Google and Jemalloc is very efficient.
The external interface is also more concise.
Worth learning.



Many other articles. Welcome attention:



Redis source code interpretation of memory management ———— Zmalloc file

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.