• 注册 / 登录
  • 切换到窄版
  • 查看: 1705|回复: 0

    带你用纯C实现一个内存池(图文)

    [复制链接]

    665

    主题

    679

    帖子

    6476

    积分

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    6476
    发表于 2023-3-26 19:07:17 | 显示全部楼层 |阅读模式

    路线栈欢迎您!

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    前言

    本文从零到一,手把手实现一个内存池。比较出名的内存池有jemalloc和tcmalloc,这两个都是全局内存池,比较推荐使用tcmalloc。

    为什么要用内存池

    为什么要用内存池?首先,在7 * 24h的服务器中如果不使用内存池,而使用malloc和free,那么就非常容易产生内存碎片,早晚都会申请内存失败;并且在比较复杂的代码或者继承的屎山中,非常容易出现内存泄漏导致mmo的问题。

    为了解决这两个问题,内存池就应运而生了。内存池预先分配一大块内存来做一个内存池,业务中的内存分配和释放都由这个内存池来管理,内存池内的内存不足时其内部会自己申请。所以内存碎片的问题就交由内存池的算法来优化,而内存泄漏的问题只需要遵守内存池提供的api,就非常容易避免内存泄漏了。

    即使出现了内存泄漏,排查的思路也很清晰。1.检查是不是内存池的问题;2.如果不是内存池的问题,就检查是不是第三方库的内存泄漏。

    内存池的使用场景

    全局内存池,一个连接一个内存池(本文实现这个场景的内存池)

    设计一个内存池

    1.总体介绍

    由于本文是一个连接一个内存池,所以后续介绍和代码都是以4k为分界线,大于4k的我们认为是大块内存;小于4k的我们认为是小块内存。并且注意这里的4k,并不是严格遵照4096,而是在描述上,用4k比较好描述。

    在真正使用内存之前,内存池提前分配一定数量且大小相等的内存块以作备用,当真正被用户调用api分配内存的时候,直接从内存块中获取内存(指小块内存),当内存块不够用了,再有内存池取申请新的内存块。而如果是需要大块内存,则内存池直接申请大块内存再返回给用户。

    内存池:就是将这些提前申请的内存块组织管理起来的数据结构,内存池实现原理主要分为分配,回收,扩容三部分。

    内存池原理之小块内存:分配=> 内存池预申请一块4k的内存块,这里称为block,即block=4k内存块。当用户向内存池申请内存size小于4k时,内存池从block的空间中划分出去size空间,当再有新申请时,再划分出去。扩容=> 直到block中的剩余空间不足以分配size大小,那么此时内存池会再次申请一块block,再从新的block中划分size空间给用户。回收=> 每一次申请小内存,都会在对应的block中引用计数加1,每一次释放小内存时,都会在block中引用计数减1,只有当引用计数为零的时候,才会回收block使他重新成为空闲空间,以便重复利用空间。这样,内存池避免频繁向内核申请/释放内存,从而提高系统性能。

    内存池原理之大块内存:分配=> 因为大块内存是大于4k的,所以内存池不预先申请内存,也就是用户申请的时候,内存池再申请内存,然后返回给用户。扩容=> 大块内存不存在扩容。回收=> 对于大块内存来说,回收就直接free掉即可。

    上面理论讲完了,下面来介绍如何管理小块内存和大块内存。

    2.小块内存的分配与管理

    在创建内存池的时候,会预先申请一块4k的内存,并且在起始处将pool的结构体和node的结构体放进去,从last开始一直到end都是空闲内存,<last , end >中间的区域就用来存储小块内存。每一次mp_malloc,就将last指针后移,直到 e n d ? l a s t < s i z e end - last < size end?last<size 时,进行扩容,将新block的last后移即可。

    初始状态:

    1.png

    分配内存:

    2.png

    扩容:

    3.png

    3.大块内存的分配与管理

    对于大块内存,前面已经说了,用户申请的时候,内存池才申请

    申请一块大内存:

    4.png

    再申请一块大内存:

    5.png

    内存池代码实现

    1.向外提供的api

    • mp_create_pool:创建一个线程池,其核心是创建struct mp_pool_s这个结构体,并申请4k内存,将各个指针指向上文初始状态的图一样。
    • mp_destroy_pool:销毁内存池,遍历小块结构体和大块结构体,进行free释放内存
    • mp_malloc:提供给用户申请内存的api
    • mp_calloc:通过mp_malloc申请内存后置零,相当于calloc
    • mp_free:释放由mp_malloc返回的内存
    • mp_reset_pool:将block的last置为初始状态,销毁所有大块内存
    • monitor_mp_poll:监控内存池状态
    1. struct mp_pool_s *mp_create_pool(size_t size);

    2. void mp_destroy_pool(struct mp_pool_s *pool);

    3. void *mp_malloc(struct mp_pool_s *pool, size_t size);

    4. void *mp_calloc(struct mp_pool_s *pool, size_t size);

    5. void mp_free(struct mp_pool_s *pool, void *p);

    6. void mp_reset_pool(struct mp_pool_s *pool);

    7. void monitor_mp_poll(struct mp_pool_s *pool, char *tk);
    复制代码

    2.相关结构体的定义

    mp_pool_s 就是整个内存池的管理结构,我们做的内存池是一个连接一个内存池,所以对于整个程序而言,内存池对象是有很多个的。

    可能读者会有疑问,有了head,为什么还有current,是因为如果一个block剩余空间小于size超过一定次数后,将current指向下一个block,这样就加快内存分配效率,减少遍历次数。

    1. //每4k一block结点
    2. struct mp_node_s {
    3.     unsigned char *end;//块的结尾
    4.     unsigned char *last;//使用到哪了
    5.     struct mp_node_s *next;//链表
    6.     int quote;//引用计数
    7.     int failed;//失效次数
    8. };

    9. struct mp_large_s {
    10.     struct mp_large_s *next;//链表
    11.     int size;//alloc的大小
    12.     void *alloc;//大块内存的起始地址
    13. };

    14. struct mp_pool_s {
    15.     struct mp_large_s *large;
    16.     struct mp_node_s *head;
    17.     struct mp_node_s *current;
    18. };
    复制代码

    3.内存对齐

    访问速度是内存对齐的原因之一,另外一个原因是某些平台(arm)不支持未内存对齐的访问

    在4k里面划分内存,那么必然有很多地方是不对齐的,所以这里提供两个内存对齐的函数。那么为什么要内存对齐呢?其一:提高访问速度;其二:某些平台arm不支持未对其的内存访问,会出错。

    1. #define mp_align(n, alignment) (((n)+(alignment-1)) & ~(alignment-1))
    2. #define mp_align_ptr(p, alignment) (void *)((((size_t)p)+(alignment-1)) & ~(alignment-1))
    复制代码

    4.创建与销毁内存池

    创建一个线程池,其核心是创建struct mp_pool_s这个结构体,并申请4k内存,将各个指针指向上文初始状态的图一样。
    销毁内存池,遍历小块结构体和大块结构体,进行free释放内存。

    1. //创建内存池
    2. struct mp_pool_s *mp_create_pool(size_t size) {
    3.     struct mp_pool_s *pool;
    4.     if (size < PAGE_SIZE || size % PAGE_SIZE != 0) {
    5.         size = PAGE_SIZE;
    6.     }
    7.     //分配4k以上不用malloc,用posix_memalign
    8.     /*
    9.         int posix_memalign (void **memptr, size_t alignment, size_t size);
    10.      */

    11.     int ret = posix_memalign((void **) &pool, MP_ALIGNMENT, size); //4K + mp_pool_s
    12.     if (ret) {
    13.         return NULL;
    14.     }
    15.     pool->large = NULL;
    16.     pool->current = pool->head = (unsigned char *) pool + sizeof(struct mp_pool_s);
    17.     pool->head->last = (unsigned char *) pool + sizeof(struct mp_pool_s) + sizeof(struct mp_node_s);
    18.     pool->head->end = (unsigned char *) pool + PAGE_SIZE;
    19.     pool->head->failed = 0;

    20.     return pool;
    21. }

    22. //销毁内存池
    23. void mp_destroy_pool(struct mp_pool_s *pool) {
    24.     struct mp_large_s *large;
    25.     for (large = pool->large; large; large = large->next) {
    26.         if (large->alloc) {
    27.             free(large->alloc);
    28.         }
    29.     }

    30.     struct mp_node_s *cur, *next;
    31.     cur = pool->head->next;

    32.     while (cur) {
    33.         next = cur->next;
    34.         free(cur);
    35.         cur = next;
    36.     }
    37.     free(pool);
    38. }
    复制代码

    6.png

    5.提供给用户的内存申请api

    申请的内存以size做区分,如果大于4k就分配大块内存,小于4k就去block里面划分。

    1. //分配内存
    2. void *mp_malloc(struct mp_pool_s *pool, size_t size) {
    3.     if (size <= 0) {
    4.         return NULL;
    5.     }
    6.     if (size > PAGE_SIZE - sizeof(struct mp_node_s)) {
    7.         //large
    8.         return mp_malloc_large(pool, size);
    9.     }
    10.     else {
    11.         //small
    12.         unsigned char *mem_addr = NULL;
    13.         struct mp_node_s *cur = NULL;
    14.         cur = pool->current;
    15.         while (cur) {
    16.             mem_addr = mp_align_ptr(cur->last, MP_ALIGNMENT);
    17.             if (cur->end - mem_addr >= size) {
    18.                 cur->quote++;//引用+1
    19.                 cur->last = mem_addr + size;
    20.                 return mem_addr;
    21.             }
    22.             else {
    23.                 cur = cur->next;
    24.             }
    25.         }
    26.         return mp_malloc_block(pool, size);// open new space
    27.     }
    28. }
    29. void *mp_calloc(struct mp_pool_s *pool, size_t size) {
    30.     void *mem_addr = mp_malloc(pool, size);
    31.     if (mem_addr) {
    32.         memset(mem_addr, 0, size);
    33.     }
    34.     return mem_addr;
    35. }
    复制代码

    6.小块内存block扩容

    所有的block都 e n d ? l a s t < s i z e end - last < size end?last<size 时,进行扩容,将新block的last后移即可。

    1. //new block 4k
    2. void *mp_malloc_block(struct mp_pool_s *pool, size_t size) {
    3.     unsigned char *block;
    4.     int ret = posix_memalign((void **) &block, MP_ALIGNMENT, PAGE_SIZE); //4K
    5.     if (ret) {
    6.         return NULL;
    7.     }
    8.     struct mp_node_s *new_node = (struct mp_node_s *) block;
    9.     new_node->end = block + PAGE_SIZE;
    10.     new_node->next = NULL;

    11.     unsigned char *ret_addr = mp_align_ptr(block + sizeof(struct mp_node_s), MP_ALIGNMENT);

    12.     new_node->last = ret_addr + size;
    13.     new_node->quote++;

    14.     struct mp_node_s *current = pool->current;
    15.     struct mp_node_s *cur = NULL;

    16.     for (cur = current; cur->next; cur = cur->next) {
    17.         if (cur->failed++ > 4) {
    18.             current = cur->next;
    19.         }
    20.     }
    21.     //now cur = last node
    22.     cur->next = new_node;
    23.     pool->current = current;
    24.     return ret_addr;
    25. }
    复制代码

    7.分配大块内存

    1. //size>4k
    2. void *mp_malloc_large(struct mp_pool_s *pool, size_t size) {
    3.     unsigned char *big_addr;
    4.     int ret = posix_memalign((void **) &big_addr, MP_ALIGNMENT, size); //size
    5.     if (ret) {
    6.         return NULL;
    7.     }

    8.     struct mp_large_s *large;
    9.     //released struct large resume
    10.     int n = 0;
    11.     for (large = pool->large; large; large = large->next) {
    12.         if (large->alloc == NULL) {
    13.             large->size = size;
    14.             large->alloc = big_addr;
    15.             return big_addr;
    16.         }
    17.         if (n++ > 3) {
    18.             break;// 为了避免过多的遍历,限制次数
    19.         }
    20.     }
    21.     large = mp_malloc(pool, sizeof(struct mp_large_s));
    22.     if (large == NULL) {
    23.         free(big_addr);
    24.         return NULL;
    25.     }
    26.     large->size = size;
    27.     large->alloc = big_addr;
    28.     large->next = pool->large;
    29.     pool->large = large;
    30.     return big_addr;
    31. }
    复制代码

    8.释放内存

    如果是大块内存,找到之后直接释放;如果是小块内存,将引用计数减1,如果引用计数为0则重置last。

    1. //释放内存
    2. void mp_free(struct mp_pool_s *pool, void *p) {
    3.     struct mp_large_s *large;
    4.     for (large = pool->large; large; large = large->next) {//大块
    5.         if (p == large->alloc) {
    6.             free(large->alloc);
    7.             large->size = 0;
    8.             large->alloc = NULL;
    9.             return;
    10.         }
    11.     }
    12.     //小块 引用-1
    13.     struct mp_node_s *cur = NULL;
    14.     for (cur = pool->head; cur; cur = cur->next) {
    15. //        printf("cur:%p   p:%p   end:%p\n", (unsigned char *) cur, (unsigned char *) p, (unsigned char *) cur->end);
    16.         if ((unsigned char *) cur <= (unsigned char *) p && (unsigned char *) p <= (unsigned char *) cur->end) {
    17.             cur->quote--;
    18.             if (cur->quote == 0) {
    19.                 if (cur == pool->head) {
    20.                     pool->head->last = (unsigned char *) pool + sizeof(struct mp_pool_s) + sizeof(struct mp_node_s);
    21.                 }
    22.                 else {
    23.                     cur->last = (unsigned char *) cur + sizeof(struct mp_node_s);
    24.                 }
    25.                 cur->failed = 0;
    26.                 pool->current = pool->head;
    27.             }
    28.             return;
    29.         }
    30.     }
    31. }
    复制代码

    内存池测试

    1. //
    2. // Created by 68725 on 2022/7/26.
    3. //
    4. #include <stdlib.h>
    5. #include <stdio.h>
    6. #include <string.h>

    7. #define PAGE_SIZE 4096
    8. #define MP_ALIGNMENT 16
    9. #define mp_align(n, alignment) (((n)+(alignment-1)) & ~(alignment-1))
    10. #define mp_align_ptr(p, alignment) (void *)((((size_t)p)+(alignment-1)) & ~(alignment-1))

    11. //每4k一block结点
    12. struct mp_node_s {
    13.     unsigned char *end;//块的结尾
    14.     unsigned char *last;//使用到哪了
    15.     struct mp_node_s *next;//链表
    16.     int quote;//引用计数
    17.     int failed;//失效次数
    18. };

    19. struct mp_large_s {
    20.     struct mp_large_s *next;//链表
    21.     int size;//alloc的大小
    22.     void *alloc;//大块内存的起始地址
    23. };

    24. struct mp_pool_s {
    25.     struct mp_large_s *large;
    26.     struct mp_node_s *head;
    27.     struct mp_node_s *current;
    28. };

    29. struct mp_pool_s *mp_create_pool(size_t size);

    30. void mp_destroy_pool(struct mp_pool_s *pool);

    31. void *mp_malloc(struct mp_pool_s *pool, size_t size);

    32. void *mp_calloc(struct mp_pool_s *pool, size_t size);

    33. void mp_free(struct mp_pool_s *pool, void *p);

    34. void mp_reset_pool(struct mp_pool_s *pool);

    35. void monitor_mp_poll(struct mp_pool_s *pool, char *tk);


    36. void mp_reset_pool(struct mp_pool_s *pool) {
    37.     struct mp_node_s *cur;
    38.     struct mp_large_s *large;

    39.     for (large = pool->large; large; large = large->next) {
    40.         if (large->alloc) {
    41.             free(large->alloc);
    42.         }
    43.     }

    44.     pool->large = NULL;
    45.     pool->current = pool->head;
    46.     for (cur = pool->head; cur; cur = cur->next) {
    47.         cur->last = (unsigned char *) cur + sizeof(struct mp_node_s);
    48.         cur->failed = 0;
    49.         cur->quote = 0;
    50.     }
    51. }

    52. //创建内存池
    53. struct mp_pool_s *mp_create_pool(size_t size) {
    54.     struct mp_pool_s *pool;
    55.     if (size < PAGE_SIZE || size % PAGE_SIZE != 0) {
    56.         size = PAGE_SIZE;
    57.     }
    58.     //分配4k以上不用malloc,用posix_memalign
    59.     /*
    60.         int posix_memalign (void **memptr, size_t alignment, size_t size);
    61.      */

    62.     int ret = posix_memalign((void **) &pool, MP_ALIGNMENT, size); //4K + mp_pool_s
    63.     if (ret) {
    64.         return NULL;
    65.     }
    66.     pool->large = NULL;
    67.     pool->current = pool->head = (unsigned char *) pool + sizeof(struct mp_pool_s);
    68.     pool->head->last = (unsigned char *) pool + sizeof(struct mp_pool_s) + sizeof(struct mp_node_s);
    69.     pool->head->end = (unsigned char *) pool + PAGE_SIZE;
    70.     pool->head->failed = 0;

    71.     return pool;
    72. }

    73. //销毁内存池
    74. void mp_destroy_pool(struct mp_pool_s *pool) {
    75.     struct mp_large_s *large;
    76.     for (large = pool->large; large; large = large->next) {
    77.         if (large->alloc) {
    78.             free(large->alloc);
    79.         }
    80.     }

    81.     struct mp_node_s *cur, *next;
    82.     cur = pool->head->next;

    83.     while (cur) {
    84.         next = cur->next;
    85.         free(cur);
    86.         cur = next;
    87.     }
    88.     free(pool);
    89. }

    90. //size>4k
    91. void *mp_malloc_large(struct mp_pool_s *pool, size_t size) {
    92.     unsigned char *big_addr;
    93.     int ret = posix_memalign((void **) &big_addr, MP_ALIGNMENT, size); //size
    94.     if (ret) {
    95.         return NULL;
    96.     }

    97.     struct mp_large_s *large;
    98.     //released struct large resume
    99.     int n = 0;
    100.     for (large = pool->large; large; large = large->next) {
    101.         if (large->alloc == NULL) {
    102.             large->size = size;
    103.             large->alloc = big_addr;
    104.             return big_addr;
    105.         }
    106.         if (n++ > 3) {
    107.             break;// 为了避免过多的遍历,限制次数
    108.         }
    109.     }
    110.     large = mp_malloc(pool, sizeof(struct mp_large_s));
    111.     if (large == NULL) {
    112.         free(big_addr);
    113.         return NULL;
    114.     }
    115.     large->size = size;
    116.     large->alloc = big_addr;
    117.     large->next = pool->large;
    118.     pool->large = large;
    119.     return big_addr;
    120. }

    121. //new block 4k
    122. void *mp_malloc_block(struct mp_pool_s *pool, size_t size) {
    123.     unsigned char *block;
    124.     int ret = posix_memalign((void **) &block, MP_ALIGNMENT, PAGE_SIZE); //4K
    125.     if (ret) {
    126.         return NULL;
    127.     }
    128.     struct mp_node_s *new_node = (struct mp_node_s *) block;
    129.     new_node->end = block + PAGE_SIZE;
    130.     new_node->next = NULL;

    131.     unsigned char *ret_addr = mp_align_ptr(block + sizeof(struct mp_node_s), MP_ALIGNMENT);

    132.     new_node->last = ret_addr + size;
    133.     new_node->quote++;

    134.     struct mp_node_s *current = pool->current;
    135.     struct mp_node_s *cur = NULL;

    136.     for (cur = current; cur->next; cur = cur->next) {
    137.         if (cur->failed++ > 4) {
    138.             current = cur->next;
    139.         }
    140.     }
    141.     //now cur = last node
    142.     cur->next = new_node;
    143.     pool->current = current;
    144.     return ret_addr;
    145. }

    146. //分配内存
    147. void *mp_malloc(struct mp_pool_s *pool, size_t size) {
    148.     if (size <= 0) {
    149.         return NULL;
    150.     }
    151.     if (size > PAGE_SIZE - sizeof(struct mp_node_s)) {
    152.         //large
    153.         return mp_malloc_large(pool, size);
    154.     }
    155.     else {
    156.         //small
    157.         unsigned char *mem_addr = NULL;
    158.         struct mp_node_s *cur = NULL;
    159.         cur = pool->current;
    160.         while (cur) {
    161.             mem_addr = mp_align_ptr(cur->last, MP_ALIGNMENT);
    162.             if (cur->end - mem_addr >= size) {
    163.                 cur->quote++;//引用+1
    164.                 cur->last = mem_addr + size;
    165.                 return mem_addr;
    166.             }
    167.             else {
    168.                 cur = cur->next;
    169.             }
    170.         }
    171.         return mp_malloc_block(pool, size);// open new space
    172.     }
    173. }

    174. void *mp_calloc(struct mp_pool_s *pool, size_t size) {
    175.     void *mem_addr = mp_malloc(pool, size);
    176.     if (mem_addr) {
    177.         memset(mem_addr, 0, size);
    178.     }
    179.     return mem_addr;
    180. }

    181. //释放内存
    182. void mp_free(struct mp_pool_s *pool, void *p) {
    183.     struct mp_large_s *large;
    184.     for (large = pool->large; large; large = large->next) {//大块
    185.         if (p == large->alloc) {
    186.             free(large->alloc);
    187.             large->size = 0;
    188.             large->alloc = NULL;
    189.             return;
    190.         }
    191.     }
    192.     //小块 引用-1
    193.     struct mp_node_s *cur = NULL;
    194.     for (cur = pool->head; cur; cur = cur->next) {
    195. //        printf("cur:%p   p:%p   end:%p\n", (unsigned char *) cur, (unsigned char *) p, (unsigned char *) cur->end);
    196.         if ((unsigned char *) cur <= (unsigned char *) p && (unsigned char *) p <= (unsigned char *) cur->end) {
    197.             cur->quote--;
    198.             if (cur->quote == 0) {
    199.                 if (cur == pool->head) {
    200.                     pool->head->last = (unsigned char *) pool + sizeof(struct mp_pool_s) + sizeof(struct mp_node_s);
    201.                 }
    202.                 else {
    203.                     cur->last = (unsigned char *) cur + sizeof(struct mp_node_s);
    204.                 }
    205.                 cur->failed = 0;
    206.                 pool->current = pool->head;
    207.             }
    208.             return;
    209.         }
    210.     }
    211. }

    212. void monitor_mp_poll(struct mp_pool_s *pool, char *tk) {
    213.     printf("\r\n\r\n------start monitor poll------%s\r\n\r\n", tk);
    214.     struct mp_node_s *head = NULL;
    215.     int i = 0;
    216.     for (head = pool->head; head; head = head->next) {
    217.         i++;
    218.         if (pool->current == head) {
    219.             printf("current==>第%d块\n", i);
    220.         }
    221.         if (i == 1) {
    222.             printf("第%02d块small block  已使用:%4ld  剩余空间:%4ld  引用:%4d  failed:%4d\n", i,
    223.                    (unsigned char *) head->last - (unsigned char *) pool,
    224.                    head->end - head->last, head->quote, head->failed);
    225.         }
    226.         else {
    227.             printf("第%02d块small block  已使用:%4ld  剩余空间:%4ld  引用:%4d  failed:%4d\n", i,
    228.                    (unsigned char *) head->last - (unsigned char *) head,
    229.                    head->end - head->last, head->quote, head->failed);
    230.         }
    231.     }
    232.     struct mp_large_s *large;
    233.     i = 0;
    234.     for (large = pool->large; large; large = large->next) {
    235.         i++;
    236.         if (large->alloc != NULL) {
    237.             printf("第%d块large block  size=%d\n", i, large->size);
    238.         }
    239.     }
    240.     printf("\r\n\r\n------stop monitor poll------\r\n\r\n");
    241. }



    242. int main() {
    243.     struct mp_pool_s *p = mp_create_pool(PAGE_SIZE);
    244.     monitor_mp_poll(p, "create memory pool");
    245. #if 0
    246.     printf("mp_align(5, %d): %d, mp_align(17, %d): %d\n", MP_ALIGNMENT, mp_align(5, MP_ALIGNMENT), MP_ALIGNMENT,
    247.            mp_align(17, MP_ALIGNMENT));
    248.     printf("mp_align_ptr(p->current, %d): %p, p->current: %p\n", MP_ALIGNMENT, mp_align_ptr(p->current, MP_ALIGNMENT),
    249.            p->current);
    250. #endif
    251.     void *mp[30];
    252.     int i;
    253.     for (i = 0; i < 30; i++) {
    254.         mp[i] = mp_malloc(p, 512);
    255.     }
    256.     monitor_mp_poll(p, "申请512字节30个");

    257.     for (i = 0; i < 30; i++) {
    258.         mp_free(p, mp[i]);
    259.     }
    260.     monitor_mp_poll(p, "销毁512字节30个");

    261.     int j;
    262.     for (i = 0; i < 50; i++) {
    263.         char *pp = mp_calloc(p, 32);
    264.         for (j = 0; j < 32; j++) {
    265.             if (pp[j]) {
    266.                 printf("calloc wrong\n");
    267.                 exit(-1);
    268.             }
    269.         }
    270.     }
    271.     monitor_mp_poll(p, "申请32字节50个");

    272.     for (i = 0; i < 50; i++) {
    273.         char *pp = mp_malloc(p, 3);
    274.     }
    275.     monitor_mp_poll(p, "申请3字节50个");


    276.     void *pp[10];
    277.     for (i = 0; i < 10; i++) {
    278.         pp[i] = mp_malloc(p, 5120);
    279.     }
    280.     monitor_mp_poll(p, "申请大内存5120字节10个");

    281.     for (i = 0; i < 10; i++) {
    282.         mp_free(p, pp[i]);
    283.     }
    284.     monitor_mp_poll(p, "销毁大内存5120字节10个");

    285.     mp_reset_pool(p);
    286.     monitor_mp_poll(p, "reset pool");

    287.     for (i = 0; i < 100; i++) {
    288.         void *s = mp_malloc(p, 256);
    289.     }
    290.     monitor_mp_poll(p, "申请256字节100个");

    291.     mp_destroy_pool(p);
    292.     return 0;
    293. }
    复制代码

    7.png

    nginx内存池对比分析

    1.相关结构体定义对比

    8.png

    2.创建内存池对比

    9.png

    3.内存申请对比

    10.png

    作者:cheems

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    小黑屋|路丝栈 ( 粤ICP备2021053448号 )

    GMT+8, 2024-9-17 03:27 , Processed in 0.050135 second(s), 21 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表