如何在C ++中处理可变大小的小对象的分配/释放

时间:2014-04-17 10:16:40

标签: c++ memory memory-management dynamic-memory-allocation

我目前正在编写C ++代码来存储和检索内存中的表格数据(例如电子表格)。数据从数据库加载。用户可以处理数据,还有一个GUI类,它应该呈现表格数据。 GUI一次只渲染几行,但表格数据可以同时包含100,000行。

我的课程如下:

  • 表:提供对行(按索引)和列定义(按列名称)的访问权限
  • 列:包含列定义,如列名称和数据类型
  • 行:包含多个字段(与列数一样多)并提供对这些字段的访问(按列名称)
  • 字段:包含一些可变长度的“原始”数据和获取/设置此数据的方法

使用此设计,包含40列和200k行的表包含超过800万个对象。经过一些实验,我发现分配和解除分配800万个对象是一项非常耗时的任务。一些研究表明,其他人正在使用自定义分配器(如Boosts pool_allocator)来解决这个问题。问题是我无法在我的问题域中使用它们,因为它们的性能提升来自于依赖于所有分配的对象具有相同大小的事实。在我的代码中并非如此,因为我的对象大小不同。

我还可以使用其他技术进行内存管理吗?或者你有关于设计的建议吗?

非常感谢任何帮助!

干杯, gdiquest

编辑:与此同时,我发现了我的问题所在。我在Visual Studio下启动了我的程序,这意味着调试器已附加到调试 - 以及发布 - 构建。使用附加的调试器,我的可执行文件使用所谓的调试堆,这非常慢。 (进一步的细节here)当我在没有附加调试器的情况下启动我的程序时,一切都和我预期的一样快。

感谢大家参与这个问题!

2 个答案:

答案 0 :(得分:2)

为什么不直接分配40块大内存?每列一个。大多数列都有固定长度的数据,这使得这些数据变得简单快捷。例如vector<int> col1(200000)。对于可变长度的,只需使用vector<string> col5(200000)Small String Optimization将确保您的短字符串不需要额外分配。只有字符串较长的行(通常> 15个字符)才需要分配。

如果你的可变长度列没有存储字符串,那么你也可以使用vector<vector<unsigned char>>这也允许一个很好的预分配策略。例如,假设此列中您最大的可变长度字段是100字节,您可以这样做:

    vector<vector<unsigned char>> col2(200000);
    for (auto& cell : col2)
    {
         cell.resize(100);
    }

现在您有一个预分配列,支持200000行,最大数据长度为100字节。我肯定会使用std::string版本,但如果你可以,因为它在概念上更简单。

答案 1 :(得分:1)

尝试rapidjson allocators,它们不仅限于相同大小的AFAIK对象。

您可以将分配器附加到表并使用它分配所有表对象 要获得更多粒度,您可能有行或列池。

Apache执行此操作,将所有数据附加到请求和连接pools

如果你希望它们与STL兼容,那么this answer可能有助于整合它们,尽管我不确定。 (我打算自己尝试这样的东西,但还没有达到目的)。

此外,某些分配器可能比系统默认提供的速度快。例如TCMalloc。 (见also)。因此,您可能希望分析并查看使用其他系统分配器是否有帮助。