最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

一文帶你玩轉(zhuǎn)C++內(nèi)存池的簡單原理及實現(xiàn)(純代碼解析)

2022-05-15 12:33 作者:補給站Linux內(nèi)核  | 我要投稿



一,為什么要用內(nèi)存池

  • C++程序默認的內(nèi)存管理(new,delete,malloc,free)會頻繁地在堆上分配和釋放內(nèi)存,導(dǎo)致性能的損失,產(chǎn)生大量的內(nèi)存碎片,降低內(nèi)存的利用率。默認的內(nèi)存管理因為被設(shè)計的比較通用,所以在性能上并不能做到極致。

  • 因此,很多時候需要根據(jù)業(yè)務(wù)需求設(shè)計專用內(nèi)存管理器,便于針對特定數(shù)據(jù)結(jié)構(gòu)和使用場合的內(nèi)存管理,比如:內(nèi)存池。

二,內(nèi)存池原理

  • 內(nèi)存池的思想是,在真正使用內(nèi)存之前,預(yù)先申請分配一定數(shù)量、大小預(yù)設(shè)的內(nèi)存塊留作備用。當有新的內(nèi)存需求時,就從內(nèi)存池中分出一部分內(nèi)存塊,若內(nèi)存塊不夠再繼續(xù)申請新的內(nèi)存,當內(nèi)存釋放后就回歸到內(nèi)存塊留作后續(xù)的復(fù)用,使得內(nèi)存使用效率得到提升,一般也不會產(chǎn)生不可控制的內(nèi)存碎片。

【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個人覺得比較好的學(xué)習書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦!??!前100名進群領(lǐng)取,額外贈送一份價值699的內(nèi)核資料包(含視頻教程、電子書、實戰(zhàn)項目及代碼)? ? ?

?

三,內(nèi)存池設(shè)計

  • 算法原理:

  1. 預(yù)申請一個內(nèi)存區(qū)chunk,將內(nèi)存中按照對象大小劃分成多個內(nèi)存塊block

  2. 維持一個空閑內(nèi)存塊鏈表,通過指針相連,標記頭指針為第一個空閑塊

  3. 每次新申請一個對象的空間,則將該內(nèi)存塊從空閑鏈表中去除,更新空閑鏈表頭指針

  4. 每次釋放一個對象的空間,則重新將該內(nèi)存塊加到空閑鏈表頭

  5. 如果一個內(nèi)存區(qū)占滿了,則新開辟一個內(nèi)存區(qū),維持一個內(nèi)存區(qū)的鏈表,同指針相連,頭指針指向最新的內(nèi)存區(qū),新的內(nèi)存塊從該區(qū)內(nèi)重新劃分和申請

  • 如圖所示:

內(nèi)存池實現(xiàn)

  • memory_pool.hpp

#ifndef _MEMORY_POOL_H_
#define _MEMORY_POOL_H_

#include <stdint.h>
#include <mutex>

template<size_t BlockSize, size_t BlockNum = 10>
class MemoryPool
{
public:
	MemoryPool()
	{
		std::lock_guard<std::mutex> lk(mtx); // avoid race condition

		// init empty memory pointer
		free_block_head = NULL;
		mem_chunk_head = NULL;
	}

	~MemoryPool()
	{
		std::lock_guard<std::mutex> lk(mtx); // avoid race condition

		// destruct automatically
		MemChunk* p;
		while (mem_chunk_head)
		{
			p = mem_chunk_head->next;
			delete mem_chunk_head;
			mem_chunk_head = p;
		}
	}

	void* allocate()
	{
		std::lock_guard<std::mutex> lk(mtx); // avoid race condition

		// allocate one object memory

		// if no free block in current chunk, should create new chunk
		if (!free_block_head)
		{
			// malloc mem chunk
			MemChunk* new_chunk = new MemChunk;
			new_chunk->next = NULL;

			// set this chunk's first block as free block head
			free_block_head = &(new_chunk->blocks[0]);

			// link the new chunk's all blocks
			for (int i = 1; i < BlockNum; i++)
				new_chunk->blocks[i - 1].next = &(new_chunk->blocks[i]);
			new_chunk->blocks[BlockNum - 1].next = NULL; // final block next is NULL
			
			if (!mem_chunk_head)
				mem_chunk_head = new_chunk;
			else
			{
				// add new chunk to chunk list
				mem_chunk_head->next = new_chunk;
				mem_chunk_head = new_chunk;
			}
		}

		// allocate the current free block to the object
		void* object_block = free_block_head;
		free_block_head = free_block_head->next; 

		return object_block;
	}

	void* allocate(size_t size)
	{
		std::lock_guard<std::mutex> lk(array_mtx); // avoid race condition for continuous memory

		// calculate objects num
		int n = size / BlockSize;

		// allocate n objects in continuous memory
		
		// FIXME: make sure n > 0
		void* p = allocate();

		for (int i = 1; i < n; i++)
			allocate();

		return p;
	}

	void deallocate(void* p)
	{
		std::lock_guard<std::mutex> lk(mtx); // avoid race condition

		// free object memory
		FreeBlock* block = static_cast<FreeBlock*>(p);
		block->next = free_block_head; // insert the free block to head
		free_block_head = block;
	}

private:
	// free node block, every block size exactly can contain one object
	struct FreeBlock
	{
		unsigned char data[BlockSize];
		FreeBlock* next;
	};

	FreeBlock* free_block_head;

	// memory chunk, every chunk contains blocks number with fixed BlockNum
	struct MemChunk
	{
		FreeBlock blocks[BlockNum];
		MemChunk* next;
	};

	MemChunk* mem_chunk_head;

	// thread safe related
	std::mutex mtx;
	std::mutex array_mtx;
};

#endif // !_MEMORY_POOL_H_

運行結(jié)果:

p1 00000174BEDE0440 1
p2 00000174BEDE0450 2
p3 00000174BEDE0450 3
p4 00000174BEDE0460 4
p5 00000174BEDD5310 5
p6 00000174BEDD5320 6
  • 可以看到內(nèi)存地址是連續(xù),并且回收一個節(jié)點后,依然有序地開辟內(nèi)存

  • 對象先開辟內(nèi)存再構(gòu)造,先析構(gòu)再釋放內(nèi)存

注意

  1. 在內(nèi)存分配和釋放的環(huán)節(jié)需要加鎖來保證線程安全

  2. 還沒有實現(xiàn)對象數(shù)組的分配和釋放


一文帶你玩轉(zhuǎn)C++內(nèi)存池的簡單原理及實現(xiàn)(純代碼解析)的評論 (共 條)

分享到微博請遵守國家法律
海城市| 黎城县| 集贤县| 昌邑市| 凤山市| 九龙坡区| 安吉县| 高要市| 郸城县| 丹江口市| 武陟县| 胶南市| 太湖县| 栖霞市| 如东县| 亚东县| 金塔县| 鲜城| 兴国县| 泽州县| 兴和县| 夹江县| 资源县| 开封市| 赤壁市| 屏南县| 贵阳市| 临沂市| 河西区| 定南县| 平江县| 卓资县| 合水县| 洮南市| 桓仁| 汉源县| 石城县| 泉州市| 温泉县| 沛县| 虞城县|