制作自己的malloc功能?

时间:2011-01-16 04:20:32

标签: c malloc

我读到有些游戏会重写自己的malloc以提高效率。我不明白在虚拟内存世界中这是如何实现的。如果我没记错的话,malloc实际上调用了一个特定于操作系统的功能,它将虚拟地址映射到MMU的真实地址。那么,如何在不调用实际运行时的malloc的情况下制作自己的内存分配器并分配实内存呢?

由于

6 个答案:

答案 0 :(得分:8)

当然,编写一个比一般用途更有效的分配器是可能的。

如果您知道分配的属性,可以将通用分配器从水中吹出来。

例如:很多年前,我们必须为嵌入式系统设计和编写通信子系统(HDLC,X.25和专有层)。事实上,我们知道最大分配总是小于128个字节(或类似的东西)意味着我们根本不需要使用可变大小的块。无论您要求多少,每个分配都是128个字节。

当然,如果你要求更多,它会返回NULL。

通过使用固定长度的块,我们能够大大加快分配和取消分配,使用位图和相关结构来保存记帐信息,而不是依赖于较慢的链接列表。此外,不需要合并释放的块。

当然,这是一个特例,但你会发现游戏也是如此。事实上,我们甚至在一个通用系统中使用它,在这个系统中,低于某个阈值的分配从自我管理的预分配池中以相同的方式获得固定数量的内存。任何其他分配(大于阈值或池已完全分配)都会发送到“真实”malloc

答案 1 :(得分:3)

仅仅因为malloc()是标准C函数并不意味着它是对内存系统的最低级访问权限。事实上,malloc()可能是根据较低级别的操作系统功能实现的。这意味着你也可以调用那些低级接口。它们可能是特定于操作系统的,但它们可能比您从malloc()接口获得更好的性能。如果是这种情况,您可以按照自己的方式实现自己的内存分配系统,并且可能更加高效 - 根据您要进行的分配大小和频率的特性优化算法,例如

答案 2 :(得分:3)

通常,malloc将调用特定于操作系统的函数来获取一堆内存(至少一个VM页面),然后根据需要将该内存划分为更小的块以返回给malloc的调用者。

malloc库还将包含一个(或列表)空闲块,因此它通常可以满足请求,而无需向操作系统请求更多内存。确定要处理多少个不同的块大小,决定是否尝试组合相邻的空闲块,等等,是malloc库实现者必须做出的选择。

您可以绕过malloc库并直接调用操作系统级别“给我一些内存”功能,并在从操作系统获得的内存中自行分配/释放。此类实现可能是特定于操作系统的。另一种方法是使用malloc进行初始分配,但保留自己的已释放对象缓存。

答案 3 :(得分:2)

你可以做的一件事就是让你的分配器分配一个内存池,然后分配来自服务请求(如果用完则分配一个更大的池)。我不确定这是不是他们正在做的事情。

答案 4 :(得分:2)

  

如果我没记错的话,实际上是malloc   调用OS特定功能

不完全。大多数硬件的页面大小为4KB。操作系统通常不公开提供小于页面大小(和页面对齐)块的任何内存分配接口。

malloc花费大部分时间来管理已经分配的虚拟内存空间,并且偶尔会从操作系统请求更多内存(显然这取决于您分配的项目的大小以及您的频率{ {1}})。

有一种常见的误解,即当你free时,它会立即返回到操作系统。虽然有时会发生这种情况(特别是对于较大的内存块),但通常情况是free d内存仍然分配给进程,然后可以在以后的free中重用。

因此,大部分工作都是在已经分配的虚拟空间的簿记中。分配策略可以有很多目标,例如快速操作,低内存浪费,良好的局部性,动态增长的空间(例如malloc)等。

如果您对内存分配和发布的模式有了更多了解,可以针对您的使用模式优化reallocmalloc,或者提供更广泛的界面。

例如,您可能正在分配大量相等大小的对象,这可能会更改最佳分配参数。或者你可能总是一次释放大量的对象,在这种情况下你不希望free做出奇特的事情。

查看memory poolsobstacks

答案 5 :(得分:1)