为什么std :: deque的效率如此之差?

时间:2013-05-24 20:32:40

标签: c++ memory vector stl deque

我想使用std :: deque,但消耗的开销内存似乎太过分了。我做错了吗?

#include "windows.h"
#include "psapi.h"

#include <iostream>
#include <vector>
#include <queue>

int main (int, char* [])
{
    PROCESS_MEMORY_COUNTERS pm;
    GetProcessMemoryInfo(GetCurrentProcess(), &pm, sizeof(pm));
    size_t mem1 = pm.WorkingSetSize;

    std::vector<int> v( 10000000 );

    GetProcessMemoryInfo(GetCurrentProcess(), &pm, sizeof(pm));
    size_t mem2 = pm.WorkingSetSize;

    std::deque<int> q( 10000000 );
    GetProcessMemoryInfo(GetCurrentProcess(), &pm, sizeof(pm));
    size_t mem3 = pm.WorkingSetSize;

    std::cout << mem2 - mem1 << std::endl;
    std::cout << mem3 - mem2 << std::endl;

    return 0;
}

输出(在32位Windows系统上):

40087552
72564736

奖金问题:为什么mem2-mem1不完全是40000000?

2 个答案:

答案 0 :(得分:4)

我不认为deques是在连续的内存块中分配的。 从(http://www.cplusplus.com/reference/deque/deque/):

  

矢量和deques都提供了一个非常相似的接口,可以用于类似的目的,但内部都以完全不同的方式工作:虽然矢量使用需要偶尔重新分配以生长的单个数组,但是deque的元素可以分散在不同的存储块中,容器在内部保存必要的信息,以便在恒定时间内使用统一的顺序接口直接访问其任何元素。因此,deques在内部比vector更复杂,但这使得它们在某些情况下可以更有效地生长,特别是在非常长的序列中,重新分配变得更加昂贵。

答案 1 :(得分:2)

如前所述,deque未分配在连续的内存块中。它必须保持数据以跟踪内存块的位置。具体细节取决于实现,但有些细节可以在STL internals: deque implementation

中找到

工作集是正在使用的物理内存量。来自working set文档。

  

进程的工作集是进程的虚拟地址空间中当前驻留在物理内存中的页面集。

有些内存已被分页到磁盘,这增加了差异性。

mem2 - mem1不等于40000000有几个原因。只需std::vector对象可能有其他成员变量。它可以跟踪大小变量并开始和结束迭代器。另一个原因是Windows堆还需要跟踪其内存,这需要内存来执行此操作。

来自Managing Heap Memory

  

但实际上,堆管理器需要额外的内存来管理堆中的内存。因此,它不是按要求分配仅100个字节,而是分配一些空间来管理每个特定的内存块。内存类型和分配大小决定了这个额外内存的大小。

您可以尝试将std::vector<int>替换为int* v = new int[10000000];,然后您会看到内存差异超过40000000字节。