我试图找出为什么我的应用程序消耗太多内存。这是:
#include <iostream>
#include <sstream>
#include <string>
#include <exception>
#include <algorithm>
#include <vector>
#include <utility>
#include <assert.h>
#include <limits.h>
#include <time.h>
#include <tchar.h>
#include <random>
typedef unsigned __int32 uint;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
vector<vector<uint>> arr(65536 * 16, vector<uint>());
mt19937 mt;
mt.seed(time(NULL));
uniform_int<uint> generator(0, arr.size() - 1);
for (uint i = 0; i < 10000000; i++)
{
for (uint j = 0; j < 16; j++)
{
uint bucketIndex = generator(mt);
arr[bucketIndex].push_back(i);
}
}
uint cap = 0;
for (uint i = 0; i < arr.size(); i++)
{
cap += sizeof(uint) * arr[i].capacity() + sizeof(arr[i]);
}
cap += sizeof(vector<uint>) * arr.capacity() + sizeof(vector<vector<uint>>);
cout << "Total bytes: " << cap << endl;
cout << "Press any key..." << endl;
cin.get();
}
我使用Windows 7 64位和Visual Studio 2010,代码也编译为64位。
代码在Debug和Release
中输出以下内容总字节数:914591424
看起来正确(您可以手动检查),但内存管理器显示该应用程序消耗〜 1.4千兆字节的内存。
这些500兆字节来自哪里?你能否告诉我如何解决这个问题?
更新
问题是由内存碎片引起的。可以通过不时压缩内存来解决。
答案 0 :(得分:2)
这是因为每个向量包含三个指针(或它们的道德和大小等价物):begin,begin + size和begin + capacity。因此,当你有一个包含大量其他小向量的向量时,每个内向量会浪费三个字(在64位系统上为24字节)。
由于每个内部向量的begin()指向单独的分配,因此您需要支付N倍的分配开销。那可能是另外几个字节。
相反,您可能希望分配单个大区域并将其视为2D数组。或者使用提供此类功能的众多库中的一个。如果你的内部矢量具有不同的大小,那么这将不起作用,但通常它们都是一个尺寸,所以你真的想要一个2D“矩形”,而不是矢量矢量。
答案 1 :(得分:1)
问题是你不知道数组的确切大小,否则你可以在实际填充之前用reserve
设置矢量容量,这样你就可以避免碎片。请尝试以下方法:
time(NULL)
)并保存以供日后使用。std::vector<uint>
的{{1}},并将其中的所有整数/计数器初始化为零,让我们将此数组/向量命名为&#34; vec_sizes&#34;。我们将使用此数组来存储/查找我们稍后将创建/填充的数组的大小。65536 * 16
一样,只需增加arr[bucketIndex].push_back(i);
计数器。现在我们知道所有载体的大小。
vec_sizes[bucketIndex]
向量。arr
中的所有子向量,调用向量的arr
方法,并在reserve
向量中找到相应的大小。这应该有效地预先分配向量,你可以避免重新分配。vec_sizes
调用已经分配了存储空间。在这里,我们利用了一个事实,即你使用伪随机生成器,如果从相同的种子开始运行它,则会给出相同的数字序列。
注意:通常当内存效率是目标时,解决方案正在进行两次工作:首先计算最终数据的不同维度,然后非常有效地分配空间/&#34;紧凑&#34;然后填写有效分配的存储空间。通常你必须牺牲一些东西。
答案 2 :(得分:1)
我与Boost Container的矢量进行了比较。并添加了shrink_to_fit
。区别:
Total bytes: 690331672 // boost::container::vector::shrink_to_fit()
Total bytes: 1120033816 // std::vector
(另请注意,boost容器永远不会在默认构造中动态分配。)
这里是代码(没有太大变化,那里):
#include <iostream>
#include <exception>
#include <algorithm>
#include <vector>
#include <utility>
#include <cassert>
#include <cstdint>
#include <random>
#include <boost/optional.hpp>
#include <boost/container/vector.hpp>
using boost::container::vector;
using boost::optional;
int main()
{
vector<vector<uint32_t>> arr(1<<20);
std::mt19937 mt;
mt.seed(time(NULL));
std::uniform_int_distribution<uint32_t> generator(0, arr.size() - 1);
for (uint32_t i = 0; i < 10000000; i++)
{
for (uint32_t j = 0; j < 16; j++)
{
auto& bucket = arr[generator(mt)];
//if (!bucket) bucket = vector<uint32_t>();
bucket.push_back(i);
}
}
for(auto& i : arr)
i.shrink_to_fit();
uint32_t cap = 0;
for (uint32_t i = 0; i < arr.size(); i++)
{
cap += sizeof(uint32_t) * arr[i].capacity() + sizeof(arr[i]);
}
cap += sizeof(vector<uint32_t>) * arr.capacity() + sizeof(arr);
std::cout << "Total bytes: " << cap << std::endl;
std::cout << "Press any key..." << std::endl;
std::cin.get();
}
更新内存配置文件
--------------------------------------------------------------------------------
Command: ./test
Massif arguments: (none)
ms_print arguments: massif.out.4193
--------------------------------------------------------------------------------
MB
822.7^ #
| @@#
| @@@@#:
| @@@@@@#:
| @@@@@@@@#:
| :@@@@@@@@@@@#:
| :::::@@:@@@@@@@@@@@#:
| @@:: ::@ :@@@@@@@@@@@#:
| @@@@@:: ::@ :@@@@@@@@@@@#:
| @@@ @@@:: ::@ :@@@@@@@@@@@#:
| :::@@@@ @@@:: ::@ :@@@@@@@@@@@#:
| @@@:::: @@@@ @@@:: ::@ :@@@@@@@@@@@#:
| @@@@@ :::: @@@@ @@@:: ::@ :@@@@@@@@@@@#:
| @@@@ @@@ :::: @@@@ @@@:: ::@ :@@@@@@@@@@@#:
| @@@:@@@@ @@@ :::: @@@@ @@@:: ::@ :@@@@@@@@@@@#:
| @@@@@@ :@@@@ @@@ :::: @@@@ @@@:: ::@ :@@@@@@@@@@@#:
| @@@@ @@@ :@@@@ @@@ :::: @@@@ @@@:: ::@ :@@@@@@@@@@@#:
| @@@@@@@@ @@@ :@@@@ @@@ :::: @@@@ @@@:: ::@ :@@@@@@@@@@@#:
| :::::::@@ @@@@@ @@@ :@@@@ @@@ :::: @@@@ @@@:: ::@ :@@@@@@@@@@@#:
| ::@:@:::: ::: @@ @@@@@ @@@ :@@@@ @@@ :::: @@@@ @@@:: ::@ :@@@@@@@@@@@#:
0 +----------------------------------------------------------------------->Gi
0 69.85