我仍然不完全確定這裏發生了什麼,但似乎內存開銷至少是問題的一部分。但是,整體內存消耗約爲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