`std :: string`分配是我目前的瓶颈 - 如何使用自定义分配器进行优化?

Vit*_*meo 13 c++ string optimization memory-management c++14

我正在编写一个C++ 14 JSON库作为练习,并在我的个人项目中使用它.

通过使用callgrind,我发现在字符串压力测试的连续值创建过程std::string中,当前的瓶颈是动态内存分配.确切地说,瓶颈就是要求malloc(...)制造的std::string::reserve.

我已经读过很多现有的JSON库,比如rapidjson使用自定义分配器来避免malloc(...)字符串内存分配期间的调用.

我试图分析rapidjson的源代码,但是大量额外的代码和注释,以及我不确定我正在寻找什么的事实,对我没什么帮助.

  • 自定义分配器如何在这种情况下提供帮助?
    • 是否在某处预先分配了内存缓冲区(静态?)并std::strings从中获取可用内存?
  • 使用自定义分配器的字符串是否与普通字符串"兼容"?
    • 他们有不同的类型.他们必须"转换"吗?(这会导致性能下降吗?)

代码说明:

  • Str是别名std::string.

iwo*_*olf 6

默认情况下,std::string根据需要从您使用malloc或分配的任何内容中分配内存new.为了通过提供自己的自定义分配器获得性能提升,您需要管理自己的"内存块",以便分配器可以更快地处理字符串要求的内存量malloc.您的内存管理器会对引擎进行相对较少的调用malloc(或者new,根据您的方法),一次请求"大量"内存,然后通过自定义分配器处理这些(这些)内存块的各个部分.要实际获得更好的性能malloc,通常必须根据用例的已知分配模式调整内存管理器.

这种事情通常归结为内存使用与执行速度之间的古老交易.例如:如果你的字符串大小在实践中有一个已知的上限,你可以通过过度分配来提取技巧以始终适应最大的情况.虽然这会浪费您的内存资源,但它可以减轻更广泛的分配与内存碎片相关的性能开销.realloc同时为您的目的拨打任何基本上不变的时间.

@sehe是完全正确的.有很多方法.

编辑:

为了最终解决您的第二个问题,使用不同分配器的字符串可以很好地一起使用,并且使用应该是透明的.

例如:

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;
}
Run Code Online (Sandbox Code Playgroud)

这是一个相当愚蠢的例子,当然,它使用相同的主力代码.但是,它显示了使用"不同类型"的分配器类在字符串之间进行分配.实现一个有用的分配器,它提供STL所需的完整接口,而不仅仅是伪装默认值,std::allocator这并不是一件容易的事.似乎是一个体面的写作,涵盖了所涉及的概念.至少在你的问题的上下文中,为什么这样做的关键是使用不同的分配器不会导致字符串具有不同的类型.请注意,自定义分配器是作为构造函数的参数而不是模板参数给出的.STL仍然使用模板(例如rebindTraits)来实现分配器接口和跟踪的均匀化.