页面边界,实现内存池

时间:2014-02-03 12:31:30

标签: windows memory pool

我决定重新发明轮子百万分之一并编写自己的内存池。我唯一的问题是关于页面大小的界限。

假设GetSystemInfo()调用告诉我页面大小为4096字节。现在,我想预先分配1MB的内存区域(可能更小或更大),并将此区域划分为128字节块。我猜,HeapAlloc()/ VirtualAlloc()的开销在8到16个字节之间。可能会更多,我读过有关60字节的帖子。

问题是,我是否需要注意不要在页面边界上有一个128字节的块?

我只是在一个块中分配1MB并将其分成块大小吗?

或者我应该分配多个块,比如4000个字节(考虑到HeapAlloc()开销),并将这4000个字节细分为128个字节块(4000/128 = 31个块,每个128个字节)和根本不使用剩余的字节(在本例中为4000 - 31x128 = 32字节)?

2 个答案:

答案 0 :(得分:1)

跨越页面边界的块不是一个大问题。它只是意味着如果您尝试访问该块并且它已完全换出,您将获得两个页面错误而不是一个。更值得担心的是块的对齐。

如果您正在使用小块来保存包含长度超过1个字节的本机类型的结构,那么您将需要对齐它,否则您将面临潜在的糟糕性能,这将超过您通过池化可能带来的任何性能提升

Windows池功能ExAllocatePool描述了其行为,如下所示:

  

如果 NumberOfBytes PAGE_SIZE或更高,则页面对齐的缓冲区为   分配。 PAGE_SIZE或更少的内存分配不会跨页面   边界。小于PAGE_SIZE的内存分配不是   必须页面对齐,但与8字节边界对齐   32位系统和64位系统中的16字节边界。

这可能是一个合理的模式。

我通常认为,当涉及到游泳池时,更大更好。当然,在合理的范围内,取决于你将如何使用它。我没有看到一次分配1 MB的任何问题(我已经制作了以100 MB块为单位的池)。您希望首先拥有游泳池是值得的。也就是说,在相同的连续内存区域中有足够的数据可以充分利用缓存局部性。

答案 1 :(得分:0)

我发现如果我使用了_align_malloc(),我就不用担心将我的子块扩展到两个页面会有所不同。 Freddie对另一个线程(How to Allocate memory from a new virtual page in C?)的回答也有所帮助。谢谢Harry Johnston,我只想将它用作内存池对象。