詳解c語言實現(xiàn)的內(nèi)存池(適用于兩個線程、不加鎖、效率高)
目的:
設(shè)計一個內(nèi)存池,要求效率比系統(tǒng)調(diào)用的效率要高(測試1萬次),同時支持一個線程申請,另外一個線程釋放。
設(shè)計思路:
因為涉及到兩個線程的申請和釋放,前期考慮加鎖的方式來實現(xiàn),但是加鎖后效率比系統(tǒng)調(diào)用的效率還要低,沒有什么意義。所以當(dāng)前的設(shè)計思路是這樣的:
1,用一個單向鏈表來維護內(nèi)存池
2,用一個[3][101]的二維數(shù)組存儲待釋放的內(nèi)存的指針。每行的第一元素表示該行是否填滿了,之后的每個元素存儲的是待釋放內(nèi)存的指針。
3,每次釋放內(nèi)存的時候并沒有真正的釋放,只是將內(nèi)存的指針填入上述數(shù)組。待填滿這一行后,將該行的第一個元素置為1。
4,在申請內(nèi)存時候遍歷這3行的第一個元素,看是否為1,如果為1,則將該行的指針全部釋放,并memset改行。
這樣真正的申請和釋放都是在一個線程的,并且兩個線程分別操作數(shù)組的不同行,不用加鎖。
線程池源碼:
memory_pool.h代碼:
#ifndef _MEMORY_POOL_H_
#define _MEMORY_POOL_H_
#define MP_ALIGNMENT 64 // 內(nèi)存對齊字節(jié)數(shù),按照32個字節(jié)進行字節(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ù)組的第二維的第一個是標(biāo)志位,表示是否已寫滿
long to_be_released[FIRST_DIMENSION][101];
// 下一個存放待釋放的指針的索引
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)存塊的個數(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)存塊的個數(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é)點
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++;
}
// 如果記錄到最后一個了就要從第一個開始記錄
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)計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,能夠解決兩個線程互斥的問題
2,用自己實現(xiàn)的內(nèi)存池測試10000次的平均時間是:207微秒,用系統(tǒng)malloc/free測試10000次的平均時間是:377微秒,時間約為系統(tǒng)調(diào)用時間的54%。而且解決了碎片問題。
備注:
一般設(shè)計的內(nèi)存池都是有局限性的,只能適用于某個場景,當(dāng)前這個內(nèi)存池只適用于一個線程申請,另外一個線程釋放的場景。
到此這篇關(guān)于c語言實現(xiàn)的內(nèi)存池(適用于兩個線程、不加鎖、效率高)的文章就介紹到這了,更多相關(guān)c語言內(nèi)存池內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++基礎(chǔ)學(xué)習(xí)之利用兩個棧實現(xiàn)一個隊列
這篇文章主要給大家介紹了關(guān)于C++基礎(chǔ)學(xué)習(xí)之利用兩個棧實現(xiàn)一個隊列的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用C++具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
C語言實現(xiàn)經(jīng)典小游戲井字棋的示例代碼
這個三子棋游戲是在學(xué)習(xí)C語言的過程中自己編寫的一個小游戲,現(xiàn)在將自己的思路(主要以流程圖形式和代碼中的注釋表達(dá))和具體代碼以及運行結(jié)果分享出來以供大家學(xué)習(xí)參考,希望對大家有所幫助2022-11-11
在C++中實現(xiàn)aligned_malloc的方法
這篇文章主要介紹了在C++中實現(xiàn)aligned_malloc的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-03-03
C++中rapidjson組裝map和數(shù)組array的代碼示例
今天小編就為大家分享一篇關(guān)于C++中rapidjson組裝map和數(shù)組array的代碼示例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-04-04

