C++ 什么时候应该在RapidJSON中使用CrtAllocator与MemoryPoolAllocator?

C++ 什么时候应该在RapidJSON中使用CrtAllocator与MemoryPoolAllocator?,c++,performance,rapidjson,C++,Performance,Rapidjson,我知道CrtAllocator是C运行时分配器,使用malloc/realloc/free,我知道MemoryPoolAllocator是默认分配器,按顺序分配内存 我不明白为什么MemoryPoolAllocator被认为比CrtAllocator更有效。MemoryPoolAllocator是否默认分配一大块内存,并且每次调用Parse()时只向其中添加条目?如果是,这是否意味着CrtAllocator为每个新的Parse()调用malloc 文档为CrtAllocator指明了这一点:当有

我知道
CrtAllocator
是C运行时分配器,使用
malloc
/
realloc
/
free
,我知道
MemoryPoolAllocator
是默认分配器,
按顺序分配内存

我不明白为什么
MemoryPoolAllocator
被认为比
CrtAllocator
更有效。
MemoryPoolAllocator
是否默认分配一大块内存,并且每次调用
Parse()
时只向其中添加条目?如果是,这是否意味着
CrtAllocator
为每个新的
Parse()
调用
malloc

文档为
CrtAllocator
指明了这一点:
当有大量添加和删除操作时,可能会首选此分配器。但是这个分配器的效率远远低于MemoryPoolAllocator。
但是它没有解释为什么添加/删除比
MemoryPoolAllocator更好,或者为什么它的效率远远低于MemoryPoolAllocator

我关心的主要用例是快速解析来自Web的JSON响应。我的计划是只分配一个大的缓冲区,并在每个响应中重用它。我想我可以使用
ParseInsitu()
每次都清除缓冲区


我在这个用例中使用哪个分配器有关系吗?

如果您只需要抓取一大块内存并实现自己的内存池,只需使用
crtAllocator
。否则,请使用
MemoryPoolAllocator
,它可以有效地从系统借用内存,并在需要时对其进行细分

使用内存池意味着,当发出内存抓取请求时,您可以让代码在用户空间中运行,因此没有上下文切换到内核/受保护模式,也不需要等待内核内存分配器的互斥量。(除非它需要借用更多内存来满足内存抓取请求,但这种情况并不常见)

需要注意的是,该程序似乎“使用”了比其他情况下需要的更多的内存;你实际上是在一个巨大的缓存上。此外,如果出现碎片问题,您可能需要注意池程序如何管理块。Delphi的
FastMM
等管理器为小型、中型和大型块提供了不同的区域来缓解这种情况

不过,在大多数情况下,内存池的任何缺点都不应该是问题;凡事要适度使用;)

查看维基百科的文章:


在您的情况下,您可能希望只使用CrtAllocator进行初始内存抓取,然后释放它并在需要增长时抓取更大的块。然后,如果系统内存受到限制,则可以考虑在稍后阶段释放。你甚至可以考虑保留一个<代码>小的块和一个<代码>大的块,这样小的块总是驻留的,但是你可以让大的块来来去去。
这样可以保持较低的内存占用,但也允许您处理大型请求,但如果内存受到限制,还可以拒绝大型请求,同时保留小的内存块,这样你就不会出现根本没有内存可抓取的情况。

从这个意义上讲,重用大缓冲区不是与内存池相同吗?是的,因此有这样一句话:“如果你只需要抓取一个大内存块并实现自己的内存池…”。如果你继续重复使用它,你就不会细分它。如果有必要,你可能需要种植它。是的,这是有道理的。因此,从技术上讲,我可以使用内存池分配器保留大量内存,并在需要时将其清除,这在功能上相当于我分配一个大缓冲区并将其传入,并在需要时将其清除。另外,为什么CrtAllocator对于频繁的添加/删除更有效?是的,这和我说的是一样的;池分配程序效率更高,但它保留内存。如果内存受到限制(由于有大量的添加/删除),那么您必须更节省地使用内存-因此CrtAllocator.Aaah得到了它。我是从性能而不是内存使用的角度来考虑效率的