C++实现简单的固定大小内存分配器

背景介绍

最近在了解性能优化相关的知识,了解到内存分配是一个可优化性能的方向,在相关书籍中看到一个固定大小的内存分配器实现,觉得挺有意思的,这里跟大家分享, 据说比通用的内存分配malloc()性能有不少提升。

源码实现

这里的代码是根据《c性能优化指南》中第13章编写的,详细的代码解析在书中有,这里就不赘述了,大家感兴趣可以瞅一瞅原文内容。

#include <iostream>
#include <algorithm>

/*memory allocator*/
struct fixed_arena_controller
{
	template<int N>
	fixed_arena_controller(char(&a)[N]);

	fixed_arena_controller(fixed_arena_controller&) = delete;
	~fixed_arena_controller() = default;
	void operator=(fixed_arena_controller&) = delete;

	void* allocate(size_t);
	size_t block_size() const;
	size_t capacity() const;
	bool empty() const;
	void clear();

private:
	void* arena_;
	size_t arena_size_;
	size_t block_size_;
};

template<int N>
inline fixed_arena_controller::fixed_arena_controller(char(&a)[N]) :
	arena_(a), arena_size_(N), block_size_(0) {}

inline void* fixed_arena_controller::allocate(size_t size)
{
	if (!empty()) {
		return nullptr;
	}

	block_size_ = std::max(size, sizeof(void*));
	size_t count = capacity();

	if (count == 0) {
		return nullptr;
	}

	char* p;
	for (p = (char*)arena_; count > 1; --count, p += size) {
		*reinterpret_cast<char**>(p) = p + size;
	}
	*reinterpret_cast<char**>(p) = nullptr;
	return arena_;
}

inline size_t fixed_arena_controller::block_size() const
{
	return block_size_;
}

inline size_t fixed_arena_controller::capacity() const
{
	return block_size_ ? (arena_size_ / block_size_) : 0;
}

inline void fixed_arena_controller::clear()
{
	block_size_ = 0;
}

inline bool fixed_arena_controller::empty() const
{
	return block_size_ == 0;
}


/*memory manager*/
template<class Arena>
struct fixed_block_memory_manager
{
	template<int N>
	fixed_block_memory_manager(char(&a)[N]);

	fixed_block_memory_manager(fixed_block_memory_manager&) = delete;
	~fixed_block_memory_manager() = default;
	void operator=(fixed_block_memory_manager&) = delete;

	void* allocate(size_t);
	size_t block_size() const;
	size_t capacity() const;
	void clear();
	void deallocate(void*);
	bool empty() const;

private:
	struct free_block
	{
		free_block* next;
	};
	free_block* free_ptr_;
	size_t		block_size_;
	Arena		arena_;
};

template<class Arena>
	template<int N>
		inline fixed_block_memory_manager<Arena>
			::fixed_block_memory_manager(char(&a)[N]) :
			arena_(a), free_ptr_(nullptr), block_size_(0)
		{}

template<class Arena>
	inline void* fixed_block_memory_manager<Arena>
		::allocate(size_t size)
{
	if (empty()) {
		free_ptr_ = reinterpret_cast<free_block*>
			(arena_.allocate(size));
		block_size_ = size;
		if (empty()) {
			throw std::bad_alloc();
		}
	}

	if (size != block_size_) {
		throw std::bad_alloc();
	}

	auto p = free_ptr_;
	free_ptr_ = free_ptr_->next;
	return p;
}

template<class Arena>
	inline void fixed_block_memory_manager<Arena>
		::deallocate(void* p)
{
	if (p == nullptr) {
		return;
	}

	auto fp = reinterpret_cast<free_block*>(p);
	fp->next = free_ptr_;
	free_ptr_ = fp;
}

template<class Arena>
	inline size_t fixed_block_memory_manager<Arena>
		::capacity() const
	{
		return arena_.capacity();
	}

template<class Arena>
	inline void fixed_block_memory_manager<Arena>
		::clear()
	{
		free_ptr_ = nullptr;
		arena_.clear();
	}

template<class Arena>
	inline bool fixed_block_memory_manager<Arena>
		::empty() const
	{
		return arena_.empty();
	}

/*operator new() for class*/
class MemMgrTester
{
private:
	int contents_;

public:
	static fixed_block_memory_manager<fixed_arena_controller> mgr_;

	MemMgrTester(int c) : contents_(c) {}

	static void* operator new(size_t s)
	{
		std::cout << "new..." << std::endl;
		return mgr_.allocate(s);
	}

	static void operator delete(void* p)
	{
		std::cout << "delete..." << std::endl;
		mgr_.deallocate(p);
	}
};

char arena[4004];
fixed_block_memory_manager<fixed_arena_controller> MemMgrTester::mgr_(arena);

int main()
{
	MemMgrTester* pObj = new MemMgrTester(100);
	delete pObj;
		 
	system("pause");
	return 0;
}

参考书籍

《C性能优化指南》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值