我正在写一个C++14 JSON 库 https://github.com/SuperV1234/SSVUtils/tree/master/include/SSVUtils/Json作为练习并在我的个人项目中使用它。
通过使用呼叫研磨我发现通过字符串压力测试持续创造价值的当前瓶颈是std::string动态内存分配。 https://github.com/SuperV1234/SSVUtils/blob/master/include/SSVUtils/Json/Io/Reader.hpp#L138-L139准确地说,瓶颈是调用malloc(...)
由...制成std::string::reserve
.
我读过许多现有的 JSON 库,例如快速JSON https://github.com/miloyip/rapidjson使用自定义分配器来避免malloc(...)
在字符串内存分配期间调用。
我尝试分析rapidjson的源代码,但是大量的附加代码和注释,加上我不太确定我在寻找什么,对我没有多大帮助。
-
How do custom allocators help in this situation?
- 内存缓冲区是否预先分配在某处(在哪里?静态地?)并且
std::strings
从中获取可用内存?
-
Are strings using custom allocators "compatible" with normal strings?
- 他们有不同的类型。他们必须“皈依”吗? (这会导致性能下降吗?)
代码注释:
默认情况下,std::string
根据需要从与您分配的任何内容相同的堆中分配内存malloc
or new
。为了通过提供您自己的自定义分配器来获得性能提升,您需要以这样的方式管理您自己的内存“块”,以便您的分配器可以比字符串更快地处理您的字符串请求的内存量。malloc
做。您的内存管理器将进行相对较少的调用malloc
, (or new
,取决于您的方法)在引擎盖下,一次请求“大量”内存,然后通过自定义分配器处理此(这些)内存块的部分。实际实现比malloc
,您的内存管理器通常必须根据用例的已知分配模式进行调整。
这种事情通常可以归结为内存使用与执行速度之间古老的权衡。例如:如果您在实践中知道字符串大小的上限,则可以通过过度分配来始终适应最大的情况。虽然这会浪费内存资源,但它可以减轻更通用的分配因内存碎片而产生的性能开销。以及拨打任何电话realloc
基本上为您的目的提供恒定的时间。
@sehe 是完全正确的。有很多方法。
EDIT:
最后要解决第二个问题,使用不同分配器的字符串可以很好地协同工作,并且使用应该是透明的。
例如:
class myalloc : public std::allocator<char>{};
myalloc customAllocator;
int main(void)
{
std::string mystring(customAllocator);
std::string regularString = "test string";
mystring = regularString;
std::cout << mystring;
return 0;
}
这是一个相当愚蠢的示例,当然,在幕后使用相同的主力代码。但是,它显示使用“不同类型”的分配器类在字符串之间进行分配。实现一个有用的分配器,提供 STL 所需的完整接口,而不仅仅是隐藏默认接口std::allocator
并不是那么微不足道。This http://www.codeproject.com/Articles/4795/C-Standard-Allocator-An-Introduction-and-Implement似乎是一篇不错的文章,涵盖了所涉及的概念。至少在您的问题的上下文中,这种方法起作用的关键在于,使用不同的分配器不会导致字符串具有不同的类型。请注意,自定义分配器作为构造函数的参数而不是模板参数给出。 STL 仍然使用模板做一些有趣的事情(例如rebind
and Traits
)以均匀化分配器接口和跟踪。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)