詳解c語言實(shí)現(xiàn)的內(nèi)存池(適用于兩個(gè)線程、不加鎖、效率高)
目的:
設(shè)計(jì)一個(gè)內(nèi)存池,要求效率比系統(tǒng)調(diào)用的效率要高(測試1萬次),同時(shí)支持一個(gè)線程申請,另外一個(gè)線程釋放。
設(shè)計(jì)思路:
因?yàn)樯婕暗絻蓚€(gè)線程的申請和釋放,前期考慮加鎖的方式來實(shí)現(xiàn),但是加鎖后效率比系統(tǒng)調(diào)用的效率還要低,沒有什么意義。所以當(dāng)前的設(shè)計(jì)思路是這樣的:
1,用一個(gè)單向鏈表來維護(hù)內(nèi)存池
2,用一個(gè)[3][101]的二維數(shù)組存儲(chǔ)待釋放的內(nèi)存的指針。每行的第一元素表示該行是否填滿了,之后的每個(gè)元素存儲(chǔ)的是待釋放內(nèi)存的指針。
3,每次釋放內(nèi)存的時(shí)候并沒有真正的釋放,只是將內(nèi)存的指針填入上述數(shù)組。待填滿這一行后,將該行的第一個(gè)元素置為1。
4,在申請內(nèi)存時(shí)候遍歷這3行的第一個(gè)元素,看是否為1,如果為1,則將該行的指針全部釋放,并memset改行。
這樣真正的申請和釋放都是在一個(gè)線程的,并且兩個(gè)線程分別操作數(shù)組的不同行,不用加鎖。
線程池源碼:
memory_pool.h代碼:
#ifndef _MEMORY_POOL_H_ #define _MEMORY_POOL_H_ #define MP_ALIGNMENT 64 // 內(nèi)存對齊字節(jié)數(shù),按照32個(gè)字節(jié)進(jìn)行字節(jié)對齊 #define BLOCK_MEM_LEN 128 // 內(nèi)存塊中申請內(nèi)存的大小 #define FIRST_DIMENSION 3 // 待釋放數(shù)組第一維 // 內(nèi)存塊結(jié)構(gòu) struct mp_block_s { struct mp_block_s *next; // 后向指針 char data[BLOCK_MEM_LEN]; }; // 內(nèi)存池結(jié)構(gòu) struct mp_pool_s { struct mp_block_s *idle; // 空閑的塊 // 待釋放的指針地址數(shù)組,數(shù)組的第二維的第一個(gè)是標(biāo)志位,表示是否已寫滿 long to_be_released[FIRST_DIMENSION][101]; // 下一個(gè)存放待釋放的指針的索引 int release_index; }; struct mp_pool_s *mp_create_pool(size_t size); void mp_free_pool(struct mp_pool_s *pool); struct mp_block_s *mp_alloc(struct mp_pool_s *pool); void mp_free(struct mp_pool_s *pool, struct mp_block_s *block); void statistics(struct mp_pool_s *pool); #endif
memory_pool.c代碼
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include "memory_pool.h" void poll_for_release(struct mp_pool_s *pool); void release_mem_block(struct mp_pool_s *pool, struct mp_block_s *block); void statistics(struct mp_pool_s *pool); /************************************************************************************************************************ * 函數(shù)功能:創(chuàng)建內(nèi)存池 * 參數(shù)說明: size ------------ 創(chuàng)建內(nèi)存塊的個(gè)數(shù) * 返 回 值: 創(chuàng)建的內(nèi)存池的指針 ************************************************************************************************************************/ struct mp_pool_s *mp_create_pool(size_t size) { struct mp_pool_s *pool; int ret = posix_memalign((void **)&pool, MP_ALIGNMENT, sizeof(struct mp_pool_s) + sizeof(struct mp_block_s) * size); if (ret) { return NULL; } memset(pool, 0, sizeof(struct mp_pool_s) + sizeof(struct mp_block_s) * size); struct mp_block_s * block = (struct mp_block_s *)((char *)pool + sizeof(struct mp_pool_s)); pool->idle = block; block->next = NULL; struct mp_block_s * tmp = block; for (int i = 1; i < size; i++) { block = (struct mp_block_s *)((char *)pool + sizeof(struct mp_pool_s) + sizeof(struct mp_block_s) * i); tmp->next = block; block->next = NULL; tmp = block; } // 初始化待釋放內(nèi)存數(shù)組 memset(pool->to_be_released, 0, FIRST_DIMENSION*101*(sizeof(long))); pool->release_index = 1; return pool; } /************************************************************************************************************************ * 函數(shù)功能:釋放內(nèi)存池 * 參數(shù)說明: size ------------ 創(chuàng)建內(nèi)存塊的個(gè)數(shù) * 返 回 值: 創(chuàng)建的內(nèi)存池的指針 ************************************************************************************************************************/ void mp_free_pool(struct mp_pool_s *pool) { // statistics(pool); free(pool); } /************************************************************************************************************************ * 函數(shù)功能:申請內(nèi)存 * 參數(shù)說明: pool ------------ 內(nèi)存池指針 * 返 回 值: 無 ************************************************************************************************************************/ struct mp_block_s *mp_alloc(struct mp_pool_s *pool) { if (!pool->idle) { printf("mem is null\n"); return NULL; } // 從idle鏈刪除,刪除首節(jié)點(diǎn) struct mp_block_s *block = pool->idle; pool->idle = block->next; // 檢查是否有需要釋放的內(nèi)存 poll_for_release(pool); return block; } /************************************************************************************************************************ * 函數(shù)功能:釋放內(nèi)存 * 參數(shù)說明: pool ------------ 內(nèi)存池指針 * 返 回 值: 無 ************************************************************************************************************************/ void release_mem_block(struct mp_pool_s *pool, struct mp_block_s *block) { // 加入到idle鏈 if (pool->idle) { block->next = pool->idle; pool->idle = block; } else { pool->idle = block; pool->idle->next = NULL; } } /************************************************************************************************************************ * 函數(shù)功能:并沒有真正的釋放,只是將當(dāng)前的內(nèi)存塊的地址添加到待釋放數(shù)組 * 參數(shù)說明: pool ------------ 內(nèi)存池指針 * 返 回 值: 無 ************************************************************************************************************************/ void mp_free(struct mp_pool_s *pool, struct mp_block_s *block) { // 數(shù)組的第一維 int first_dimension = pool->release_index / 101; // 數(shù)組的第二維 int second_dimension = pool->release_index % 101; pool->to_be_released[first_dimension][second_dimension] = (long)block; if (second_dimension == 100) { // 標(biāo)志置為1表示這行滿了 pool->to_be_released[first_dimension][0] = 1; pool->release_index = pool->release_index + 2; } else { pool->release_index++; } // 如果記錄到最后一個(gè)了就要從第一個(gè)開始記錄 if (pool->release_index == (FIRST_DIMENSION * 101 + 1)) { pool->release_index = 1; } } /************************************************************************************************************************ * 函數(shù)功能:遍歷待釋放數(shù)組,看是否需要真正釋放內(nèi)存。 * 參數(shù)說明: pool ------------ 內(nèi)存池指針 * 返 回 值: 無 ************************************************************************************************************************/ void poll_for_release(struct mp_pool_s *pool) { for (int i = 0; i < FIRST_DIMENSION; i++) { if (pool->to_be_released[i][0]) { for (int j = 0; j < 100; j++) { release_mem_block(pool, (struct mp_block_s *)(pool->to_be_released[i][j + 1])); } memset(pool->to_be_released[i], 0, 101 * sizeof(long)); } } } /************************************************************************************************************************ * 函數(shù)功能:統(tǒng)計(jì)idle和allocated的數(shù)量 * 參數(shù)說明: pool ------------ 內(nèi)存池指針 * 返 回 值: 無 ************************************************************************************************************************/ void statistics(struct mp_pool_s *pool) { int idle = 0; struct mp_block_s *block = pool->idle; while(block) { // printf("statistics, idle, block = %p, block->next = %p\n", block, block->next); block = block->next; idle++; } printf("idle = %d\n", idle); for (int i = 0; i < FIRST_DIMENSION; i++) { for (int j = 0; j < 101; j++) { printf("%p, ", (void*)(pool->to_be_released[i][j])); } printf("\n"); } }
測試代碼:
memory_pool_test.c 代碼:
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <time.h> #include "memory_pool.h" int timespec_minus(struct timespec *a, struct timespec *b) { return (a->tv_sec - b->tv_sec) * 1000000 + (int)((a->tv_nsec - b->tv_nsec)/1000); } int main(int argc, char *argv[]) { int size = 1024; printf("size = %d\n", size); struct mp_pool_s *pool = mp_create_pool(size); printf("mp_create_pool over\n"); // statistics(pool); struct timespec before, after; clock_gettime(CLOCK_MONOTONIC, &before); struct mp_block_s *block = NULL; int i = 0; for (i = 0;i < 10000;i ++) { block = mp_alloc(pool); mp_free(pool, block); // if (i % 100 == 0) { // statistics(pool); // } } // statistics(pool); clock_gettime(CLOCK_MONOTONIC, &after); int delay = timespec_minus(&after, &before); printf("mempool malloc 10000 times : %d microsecond\n", delay); mp_free_pool(pool); clock_gettime(CLOCK_MONOTONIC, &before); char * p = NULL; for (i = 0;i < 10000;i ++) { p = malloc(128); free(p); } clock_gettime(CLOCK_MONOTONIC, &after); delay = timespec_minus(&after, &before); printf("system malloc 10000 times : %d microsecond\n", delay); return 0; }
測試結(jié)果:
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# make
cc os_mutex.c memory_pool.c memory_pool_test.c -o memory_pool_test -lpthread
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 154 microsecond
system malloc 10000 times : 366 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 136 microsecond
system malloc 10000 times : 333 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 163 microsecond
system malloc 10000 times : 333 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 136 microsecond
system malloc 10000 times : 334 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 154 microsecond
system malloc 10000 times : 349 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 298 microsecond
system malloc 10000 times : 351 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 143 microsecond
system malloc 10000 times : 342 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 139 microsecond
system malloc 10000 times : 333 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 164 microsecond
system malloc 10000 times : 350 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 191 microsecond
system malloc 10000 times : 333 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 308 microsecond
system malloc 10000 times : 542 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 178 microsecond
system malloc 10000 times : 355 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 304 microsecond
system malloc 10000 times : 349 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 327 microsecond
system malloc 10000 times : 453 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 213 microsecond
system malloc 10000 times : 333 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 306 microsecond
system malloc 10000 times : 578 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 160 microsecond
system malloc 10000 times : 333 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 334 microsecond
system malloc 10000 times : 355 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 189 microsecond
system malloc 10000 times : 333 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 204 microsecond
system malloc 10000 times : 349 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 384 microsecond
system malloc 10000 times : 333 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 295 microsecond
system malloc 10000 times : 333 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 306 microsecond
system malloc 10000 times : 509 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 151 microsecond
system malloc 10000 times : 333 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 189 microsecond
system malloc 10000 times : 364 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 146 microsecond
system malloc 10000 times : 332 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 190 microsecond
system malloc 10000 times : 337 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 159 microsecond
system malloc 10000 times : 333 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 204 microsecond
system malloc 10000 times : 341 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 188 microsecond
system malloc 10000 times : 333 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 213 microsecond
system malloc 10000 times : 341 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 138 microsecond
system malloc 10000 times : 342 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 146 microsecond
system malloc 10000 times : 333 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 324 microsecond
system malloc 10000 times : 550 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 143 microsecond
system malloc 10000 times : 344 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 278 microsecond
system malloc 10000 times : 333 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 149 microsecond
system malloc 10000 times : 341 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 146 microsecond
system malloc 10000 times : 336 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 150 microsecond
system malloc 10000 times : 344 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 324 microsecond
system malloc 10000 times : 369 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 223 microsecond
system malloc 10000 times : 336 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 208 microsecond
system malloc 10000 times : 335 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 146 microsecond
system malloc 10000 times : 333 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool# ./memory_pool_test
size = 1024
mp_create_pool over
mempool malloc 10000 times : 151 microsecond
system malloc 10000 times : 333 microsecond
(base) root@liyan-virtual-machine:/home/zhangmeng/test/memory_pool#
測試結(jié)論:
1,能夠解決兩個(gè)線程互斥的問題
2,用自己實(shí)現(xiàn)的內(nèi)存池測試10000次的平均時(shí)間是:207微秒,用系統(tǒng)malloc/free測試10000次的平均時(shí)間是:377微秒,時(shí)間約為系統(tǒng)調(diào)用時(shí)間的54%。而且解決了碎片問題。
備注:
一般設(shè)計(jì)的內(nèi)存池都是有局限性的,只能適用于某個(gè)場景,當(dāng)前這個(gè)內(nèi)存池只適用于一個(gè)線程申請,另外一個(gè)線程釋放的場景。
到此這篇關(guān)于c語言實(shí)現(xiàn)的內(nèi)存池(適用于兩個(gè)線程、不加鎖、效率高)的文章就介紹到這了,更多相關(guān)c語言內(nèi)存池內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++基礎(chǔ)學(xué)習(xí)之利用兩個(gè)棧實(shí)現(xiàn)一個(gè)隊(duì)列
這篇文章主要給大家介紹了關(guān)于C++基礎(chǔ)學(xué)習(xí)之利用兩個(gè)棧實(shí)現(xiàn)一個(gè)隊(duì)列的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用C++具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05C語言實(shí)現(xiàn)經(jīng)典小游戲井字棋的示例代碼
這個(gè)三子棋游戲是在學(xué)習(xí)C語言的過程中自己編寫的一個(gè)小游戲,現(xiàn)在將自己的思路(主要以流程圖形式和代碼中的注釋表達(dá))和具體代碼以及運(yùn)行結(jié)果分享出來以供大家學(xué)習(xí)參考,希望對大家有所幫助2022-11-11Linux中rm命令使用以及C/C++代碼實(shí)現(xiàn)
m 是remove 的縮寫,Linux中 rm 命令的功能為刪除一個(gè)目錄中的一個(gè)或多個(gè)文件或目錄,它也可以將某個(gè)目錄及其下的所有文件及子目錄均刪除,這篇文章主要給大家介紹了關(guān)于Linux中rm命令使用以及C/C++代碼實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下2022-04-04在C++中實(shí)現(xiàn)aligned_malloc的方法
這篇文章主要介紹了在C++中實(shí)現(xiàn)aligned_malloc的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03C++中rapidjson組裝map和數(shù)組array的代碼示例
今天小編就為大家分享一篇關(guān)于C++中rapidjson組裝map和數(shù)組array的代碼示例,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-04-04