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

2023-11-18

背景介绍

最近在了解性能优化相关的知识,了解到内存分配是一个可优化性能的方向,在相关书籍中看到一个固定大小的内存分配器实现,觉得挺有意思的,这里跟大家分享, 据说比通用的内存分配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性能优化指南》

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • 使用 std::packaged_task/std::exception_ptr 时,线程清理程序报告数据争用

    我遇到了线程清理程序 TSan 的一些问题 抱怨某些生产代码中的数据争用 其中 std packaged task 通过将它们包装在 std function 中而移交给调度程序线程 对于这个问题 我简化了它在生产中的作用 同时触发 TSa
  • 注销租约抛出 InvalidOperationException

    我有一个使用插件的应用程序 我在另一个应用程序域中加载插件 我使用 RemoteHandle 类http www pocketsilicon com post Things That Make My Life Hell Part 1 App
  • 为什么 int8_t 和用户通过 cin 输入显示奇怪的结果[重复]

    这个问题在这里已经有答案了 一小段代码让我发疯 但希望你能阻止我跳出窗外 看这里 include
  • 如何让 Swagger 插件在自托管服务堆栈中工作

    我已经用 github 上提供的示例重新提出了这个问题 并为任何想要自己运行代码的人提供了一个下拉框下载链接 Swagger 无法在自托管 ServiceStack 服务上工作 https stackoverflow com questio
  • 确保 StreamReader 不会挂起等待数据

    下面的代码读取从 tcp 客户端流读取的所有内容 并且在下一次迭代中它将仅位于 Read 上 我假设正在等待数据 我如何确保它不会在没有任何内容可供读取时返回 我是否必须设置低超时 并在失败时响应异常 或者有更好的办法吗 TcpClient
  • 计算 Richtextbox 中所有单词的最有效方法是什么?

    我正在编写一个文本编辑器 需要提供实时字数统计 现在我正在使用这个扩展方法 public static int WordCount this string s s s TrimEnd if String IsNullOrEmpty s re
  • 复制 std::function 的成本有多高?

    While std function是可移动的 但在某些情况下不可能或不方便 复制它会受到重大处罚吗 它是否可能取决于捕获变量的大小 如果它是使用 lambda 表达式创建的 它依赖于实现吗 std function通常被实现为值语义 小缓
  • 在 C 中匹配二进制模式

    我目前正在开发一个 C 程序 需要解析一些定制的数据结构 幸运的是我知道它们是如何构造的 但是我不确定如何在 C 中实现我的解析器 每个结构的长度都是 32 位 并且每个结构都可以通过其二进制签名来识别 举个例子 有两个我感兴趣的特定结构
  • 当我们想要返回对象的引用时,为什么我们在赋值运算符中返回 *this 而通常(而不是 this)?

    我正在学习 C 和指针 我以为我理解了指针 直到我看到这个 一方面 asterix 运算符是解引用的 这意味着它返回值所指向的地址中的值 而与号 运算符则相反 它返回值存储的地址记忆 现在阅读有关赋值重载的内 容 它说 我们返回 this因
  • 回发后刷新时提示确认表单重新提交。我做错了什么?

    我有一个以空白 默认状态启动的仪表板 我让用户能够将保存的状态加载到仪表板中 当他们单击 应用 按钮时 我运行以下代码 function CloseAndSave var radUpload find radUpload1ID var in
  • 在 C 中初始化变量

    我知道有时如果你不初始化int 如果打印整数 您将得到一个随机数 但将所有内容初始化为零似乎有点愚蠢 我问这个问题是因为我正在评论我的 C 项目 而且我对缩进非常直接 并且它可以完全编译 90 90 谢谢 Stackoverflow 但我想
  • 是否有实用的理由使用“if (0 == p)”而不是“if (!p)”?

    我倾向于使用逻辑非运算符来编写 if 语句 if p some code 我周围的一些人倾向于使用显式比较 因此代码如下所示 if FOO p some code 其中 FOO 是其中之一false FALSE 0 0 0 NULL etc
  • 从 Linux 内核模块中调用用户空间函数

    我正在编写一个简单的 Linux 字符设备驱动程序 以通过 I O 端口将数据输出到硬件 我有一个执行浮点运算的函数来计算硬件的正确输出 不幸的是 这意味着我需要将此函数保留在用户空间中 因为 Linux 内核不能很好地处理浮点运算 这是设
  • 标准化 UTF-8 到底是什么?

    The 重症监护室项目 http userguide icu project org transforms normalization 现在也有一个PHP库 http us php net manual en class normalize
  • 在一个平台上,对于所有数据类型,所有数据指针的大小是否相同? [复制]

    这个问题在这里已经有答案了 Are char int long 甚至long long 大小相同 在给定平台上 不能保证它们的大小相同 尽管在我有使用经验的平台上它们通常是相同的 C 2011 在线草稿 http www open std
  • C# HashSet 只读解决方法

    这是示例代码 static class Store private static List
  • C# 中的合并运算符?

    我想我记得看到过类似的东西 三元运算符 http msdn microsoft com en us library ty67wk28 28VS 80 29 aspx在 C 中 它只有两部分 如果变量值不为空 则返回变量值 如果为空 则返回默
  • 动态添加 ASP.Net 控件

    我有一个存储过程 它根据数据库中存储的记录数返回多行 现在我想有一种方法来创建 div 带有包含该行值的控件的标记 如果从数据库返回 10 行 则 10 div 必须创建标签 我有下面的代码来从数据库中获取结果 但我不知道如何从这里继续 S
  • C++ 条件编译

    我有以下代码片段 ifdef DO LOG define log p record p else define log p endif void record char data 现在如果我打电话log hello world 在我的代码中
  • 如何将 PostgreSql 与 EntityFramework 6.0.2 集成? [复制]

    这个问题在这里已经有答案了 我收到以下错误 实体框架提供程序类型的 实例 成员 Npgsql NpgsqlServices Npgsql 版本 2 0 14 2 文化 中性 PublicKeyToken 5d8b90d52f46fda7 没

随机推荐

  • H5打开新窗口与页面跳转的几种方法

    1 在本窗体打开一个新的页面 window location href URL 2 在一个新的窗口打开一个新的页面 window open URL 3 本窗口的页面被替换为一个新的页面URL 替换后不可以回退到上个页面 location r
  • 理光打印机出现sc542-01怎样解决?

    问题图 步骤一图文 补充 理光维修模式指令 107 03以下机型 143 通用 806182 03以上机型 注方法 1 清除键 黄色 点一次 107 停止键 红色键 按住3秒以上 2 依次按重置 RESET 806182 按住C不动3秒 就
  • CentOS7.5最小化安装之后的配置

    我是最小化安装的 安装了之后很多基本使用配置没有 接下来要做一些配置 如网络之类的 使系统可用 1 使命令分页显示 1页显示不不下 又不能上翻页 xxx more 2 查看系统安装了哪些软件包 rpm qa 3 配置网络 最小化安装之后 i
  • 听我一句劝,别去外包,干了3个月,技术退步明显...

    先说一下自己的情况 大专生 18年通过校招进入湖南某软件公司 干了接近4年的功能测试 今年年初 感觉自己不能够在这样下去了 长时间呆在一个舒适的环境会让一个人堕落 而我已经在一个企业干了四年的功能测试 已经让我变得不思进取 谈了2年的女朋友
  • 一种关于单片机定时器中断和数码管冲突问题的解决方案

    问题发现 我们会发现 同时存在定时器中断和数码管操作时 有时会导致数码管显示异常 原因探究 在定时器中断函数中不要操作P2和P0 因为定时器 T 和主板 M 的时钟频率不一样 有可能导致M刚操作完P2 T又去操作P0 导致正确的P2和P0没
  • Windows从命令行创建文本文件的两种方式

    第一种方式 copy con 文件名 然后可以输入文件内容 完成后打Ctrl Z退出 输入的内容被保存为一个文件 第二种 如下 echo gt 文件名 创建一个空的文件 当然你可以创建任何后缀名的文本类文件 创建一个SQL文件也是没问题的
  • 教你更优雅的写法处理null检查

    回顾以前对null的处理方式 public class OptionalTest public static void main String args test01 小黑 test01 null public static void te
  • View.VISIBLE、INVISIBLE、GONE的区别

    View VISIBLE INVISIBLE GONE的区别 android中UI应用的开发中经常会使用view setVisibility 来设置控件的可见性 其中该函数有3个可选值 他们有着不同的含义 View VISIBLE gt 可
  • Qt事件和事件循环

    在处理QT循环事件的时候遇到了问题 查了半天资料都没弄明白问题出在哪 后来找大牛同事问了一下 同事就给我写了QCoreApplication processEvent 这个函数 好啦 终于搞定了 这里小记一下 以免以后遇到 于是乎这里认真仔
  • Your account has been blocked问题解决

    更新代码时报错 如下 branches to build service 1 get branch service to dir service only update code Your account has been blocked
  • 2020规划调整,以自研引擎和osg/osgearth源码分析为主

    随着公司转入webgl 我要求调整到osg osgearth工具 因为是c 方面的 特别是osg osgearth源码可以深入下 以前光把视频教程看过 说白了就是简单二次应用 并没有深入下去 所以 趁此机会多读读osg osgearth源码
  • 计算机系统(一)——冯诺依曼体系

    现代计算机的基本结构是由冯诺依曼提出的 冯诺依曼的体系结构体系如下图所示 计算机由运算器 控制器 存储器 也就是内存 输入设备 输出设备五大部件组成 其中运算器和控制器组成cpu 在冯诺依曼体系中 数据先从输入设备输入到内存中 运算时数据从
  • 解决使用SpringBoot上传文件大小受限问题

    今天在做项目学习的过程中 需要用到文件上传 启动项目正常 访问上传post请求突然报出了一个异常 特此记录一下 1 控制台异常 org springframework web multipart MaxUploadSizeExceededE
  • 一起赚美元①

    译者 一只椰子 知识星球链接 https t zsxq com iAiIyfm 本文的主人公叫迈克 他在采访里面提到 自动化工具这一法宝已经轻松帮他实现每个月 12 5万美元的利润 对他而言 年入100万美元 根本不是梦 1 主人公简介 我
  • 看完这篇,成为Grafana高手!

    背景 QQ直播前端团队接入腾讯云前端性能监控 RUM 后 对目前的监控能力以及上报数据进行了梳理 并着手进行了前端性能监控的专项建设 其中监控数据大盘建设是不可或缺的一环 可视化的监控大盘可以清晰明了的观察到各项目运行情况 宏观上能快速进行
  • 【ESP32S2】使用ESP32S2开发板制作U盘,支持无线访问

    文章目录 前言 一 开发环境 二 硬件介绍 三 下载esp idf 四 下载esp iot solution 五 配置idf 1 执行下载脚本 2 设置环境变量 3 声明外部组件 六 构建例程 七 烧写Flash 八 使用方法 九 感谢 前
  • 深度学习之Python,OpenCV中的卷积

    这篇博客将介绍图像内核和卷积 如果将图像视为一个大矩阵 那么图像内核只是一个位于图像顶部的微小矩阵 从左到右和从上到下滑动内核 计算输入图像和内核之间的元素乘法总和 称这个值为内核输出 内核输出存储在与输入图像相同 x y 坐标的输出图像中
  • 3D游戏第九次作业

    3D游戏第九次作业 1 血条 Health Bar 的预制设计 具体要求如下 分别使用 IMGUI 和 UGUI 实现 使用 UGUI 血条是游戏对象的一个子元素 任何时候需要面对主摄像机 分析两种实现的优缺点 给出预制的使用方法 IMGU
  • 2、为什么选择URP

    为什么选择URP 现在所在项目为SLG类项目 有同屏200 英雄的需求 Unity传统渲染管线的动态批处理有个限制是Skined Mesh Renderer不能进行动态批处理 英雄如果不采用Skined Mesh Renderer又不能满足
  • C++实现简单的固定大小内存分配器

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