64位计算机上的stl向量大小

时间:2012-07-02 14:23:29

标签: c++ stl vector

我有一个将使用数百万个载体的应用程序。

似乎std :: vector的大多数实现使用4个指针(_First,_Last,_End和_Alloc),它们在64位计算机上消耗32个字节。对于矢量的大多数“实际”用例,人们可能会使用单个指针和两个“unsigned int”字段来存储当前大小&分别分配大小。忽略支持自定义分配的潜在挑战(而不是假设分配必须通过全局新的& delete运算符),似乎可以构建一个仅使用16个字节(或最差24个字节)的STL兼容向量类支持_Alloc指针。)

在我开始编码之前,1)我是否应该注意任何陷阱; 2)是否存在开源实现?

3 个答案:

答案 0 :(得分:5)

你可以做到这样的事情 - 但你不可能获得那么多。

首先,有性能方面。你正在交换内存消耗的时间。无论你保存什么内存,都要通过对end的每次调用进行加法和乘法来抵消(好吧,如果它是一个向量,其中sizeof(vector<t>::value_type) == 1乘法可以被优化掉)。请注意,大多数手写的循环代码都会在每次循环迭代时调用end。在现代CPU上,它实际上将成为一个重大胜利,因为它允许处理器在缓存中保留更多内容;除非内循环中的那些额外指令迫使处理器过于频繁地交换指令高速缓存中的内容。

此外,就向量中的总体内存使用而言,内存节省可能很小,原因如下:

  • 内存管理器开销。来自内存管理器的每个分配(当然需要哪个向量)将在大多数内存管理器实现中自己添加16-24字节的开销。 (假设类似dlmalloc(UNIX / Linux /等)或RtlHeap(Windows))
  • 过度配置负载。为了在结束时实现分摊的常量插入和移除,当向量调整大小时,它将调整大小到向量中数据大小的某个倍数。这意味着典型的内存容量向量分配足以使1.6(MSVC ++)或2(STLPort,libstdc ++)乘以实际存储在向量中的元素数量。
  • 对齐限制。如果要将这些向量放入数组(或其他向量),请记住该向量的第一个成员仍然是指向已分配内存块的指针。这个指针通常需要8字节对齐 - 所以你保存的4个字节会丢失到数组中的结构填充。

我现在使用vector的简单实现。如果您通过内存分析器运行代码,并发现通过删除这些指针可以节省大量成本,那么您可能不会实现自己的优化类来满足您的性能特征,而不是依赖于内置的矢量实现。 (在这些实现小字符串优化的平台上,一个这样的优化类的例子是std::string

(注意:我所知道的唯一优化了Alloc指针的编译器是VC11,它还没有发布。虽然Nim说当前的libstdc ++预发布版本也是如此。 。)

答案 1 :(得分:1)

除非这些向量的内容非常小,否则保存内容的16和32字节之间的差异将占它们消耗的总内存的一小部分。要重新发明这个轮子需要付出很多努力,所以一定要为所有工作获得足够的回报。

顺便说一句,教育也很有价值,你会通过这样做学到很多东西。如果您选择继续,您可以考虑先编写一个测试套件,然后在当前实现上运行它,然后再在您发明的实现上。

答案 2 :(得分:0)

要回答是否值得付出努力,找到或编写符合 需求的兼容实现(也许std :: vector中还有其他你不需要的东西),并比较在相关平台上使用std::vector<your_type>的效果。您的建议至少可以提高移动构造函数以及移动赋值运算符的性能:

typedef int32_t v4si __attribute__ ((vector_size (16)));
union
    {
    v4si data;
    struct
        {
        T* pointer;
        uint32_t length;
        uint32_t capacity;
        } content;
    } m_data;

这只涵盖&#34;理智&#34; T(noexcept move semantices)。 https://godbolt.org/g/d5yU3o