我仍然不完全确定这里发生了什么,但似乎内存开销至少是问题的一部分。但是,整体内存消耗约为data
结构所需的4倍。如果有27M记录占用14GB,则每个记录大约有500个字节,但占用的空间是56GB。对我而言,这表示存储的数据比我们在此处显示的要多,或者至少有一些数据存储了多次。
而“堆存储的额外数据”并不是真的为我做。在Linux中,内存分配需要大约32个字节的数据。 16字节的开销,分配的内存占用16个字节的倍数。
所以对于存储在多重映射一个data *
记录,我们需要:
16 bytes of header for the memory allocation
8 bytes for pointer of `value1`
8 bytes for pointer of `value2`
16 bytes of header for the string in value1
16 bytes of header for the string in value2
8 bytes (on average) "size rounding" for string in value 1
8 bytes (on average) "size rounding" for string in value 2
?? bytes from the file. (X)
80 + X bytes total.
然后我们有char *
在多重映射:
16 bytes of header for the memory allocation.
8 bytes of rounding on average.
?? bytes from the file. (Y)
24 + Y bytes total.
multimap中的每个节点有两个指针(我假设它是某种二叉树):
16 bytes of header for the memory allocation of the node.
8 bytes of pointer to "left"
8 bytes of pointer to "right"
32 bytes total.
所以,tha t会为文件中的每个条目创建136个字节的“开销”。对于27M的记录,这只是超过4GB。
正如我所说,该文件包含每个条目500字节,因此使得14GB。
总共18GB。
所以,在某个地方,有些东西要么泄漏,要么数学是错误的。我可能会在这里计算结果,但即使上面的所有数据都是我计算的空间的两倍,但仍有20GB的数据不明。
当然,还有一些事情我们可以做,以节省内存:
1)不要在data
分配两个字符串。第一计算两个长度,分配的存储器的一个块,并且在彼此之后立即存储字符串:
data(char* _value1, char* _value2)
{
int len1 = strlen(_value1);
int len2 = strlen(_value2);
value1 = new char[len1 + len2 +2];
strcpy(value1,_value1);
value2 = value1 + len1 + 1;
strcpy(value2,_value2);
}
这将节省每条目平均24个字节。我们可以通过聪明并一次分配数据,值1和值2的内存来节省更多。但这可能有点“太聪明”了。
2)分配一大块data
物品,并且每次放一个物品也会有所帮助。对于这项工作,我们需要一个空的构造,以及“setValues方法”的方法:
struct data
{
...
data() {};
...
set_values(char* _value1, char* _value2)
{
int len1 = strlen(_value1);
int len2 = strlen(_value2);
value1 = new char[len1 + len2 +2];
strcpy(value1,_value1);
value2 = value1 + len1 + 1;
strcpy(value2,_value2);
}
}
std::string v1[100], v2[100], key[100];
for(i = 0; i < 100; i++)
{
if (!read_line_from_file(key[i], v1[i], v2[i]))
{
break;
}
}
data* data_block = new data[i];
for(j = 0; j < i; j++)
{
data_block[j].setValues[v1[j].c_str(), v2[j].c_str());
m.insert(key[i].c_str(), &data_block[j]);
}
再次,这将不保存的内存量巨大,但每个16字节的区域可以节省一些内存。以上当然不是完整的代码,更多的是“如何完成”的说明。 3)我仍然不确定“密钥”来自multimap的位置,但如果密钥是value1和value2条目之一,那么您可以重用其中的一个,而不是存储另一个副本[假设这是目前的做法]。
对不起,如果这不是一个真正的答案,但我确实相信这是一个答案,“某处,某事在你解释你正在做的事情时不知情”。
了解在程序中分配的内容肯定会有所帮助。
您是否尝试过轻量级设计模式? – Deamonpog 2013-02-15 16:33:35
您可以查看[boost平面关联容器](http://www.boost.org/doc/libs/1_53_0/doc/html/container/non_standard_containers.html#container.non_standard_containers.flat_xxx)。当然,性能权衡,特别是插入。 – juanchopanza 2013-02-15 16:39:11
我不想使用任何外部库。根据我的项目指南,我应该使用C++标准库。 – Manish 2013-02-15 16:40:50