나는 아직도 어떤 일이 일어나고 있는지 확실하지 않지만 메모리 오버 헤드가 문제의 적어도 일부라고 생각합니다. 그러나 전체 메모리 소비는 data
구조에 필요한 약 4 배입니다. 27M 레코드가 14GB를 차지하지만 레코드 공간이 56GB 인 경우 레코드 당 약 500 바이트가 있습니다. 나에게 이것은 여기에 표시된 것보다 더 많은 데이터가 저장되어 있거나 적어도 일부 데이터가 두 번 이상 저장되었음을 나타냅니다.
"힙 스토리지를위한 추가 데이터"는 실제로 나를 위해 그것을하지 않습니다. 리눅스에서 메모리 할당은 약 32 바이트의 데이터를 가져온다. 오버 헤드가 16 바이트이고 할당 된 메모리 자체가 16 바이트의 배수가됩니다.
는 그래서 multimap에 저장 한 data *
기록, 우리는 필요한 다음과 multimap의 각 노드는 두 개의 포인터를해야합니다
16 bytes of header for the memory allocation.
8 bytes of rounding on average.
?? bytes from the file. (Y)
24 + Y bytes total.
(I :
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.
우리는 다음과 multimap에 char *
이 일종의 이진 트리라고 가정) :
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.
그래서, 그쪽으로 파일에서 항목 당 136 바이트의 "오버 헤드"를 만듭니다. 27M 레코드의 경우 4GB가 조금 넘습니다.
파일에는 내가 말한 것처럼 항목 당 500 바이트가 포함되어 있으므로 14GB가됩니다.
총 18GB입니다.
어딘가에 뭔가 누수가 있거나 수학이 잘못되었습니다. 여기서 계산을 할 수는 있지만, 위의 모든 것이 계산 된 공간의 두 배가 되더라도 계산되지 않은 20GB의 공간이 있습니다.
1) data
에서 두 문자열을 할당하지 마십시오
확실히 우리가 메모리를 절약하기 위해 할 수있는 몇 가지가 있습니다. 먼저 두 길이를 계산 메모리를 하나 개의 덩어리를 할당하고, 서로 직후 문자열을 저장 : 항목 당 평균 24 바이트를 절약 할 수
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);
}
합니다. 똑똑하고 데이터 value1과 value2에 대한 메모리를 한꺼번에 할당함으로써 훨씬 더 많은 것을 저장할 수 있습니다. 그러나 그것은 약간 "너무 똑똑 할"수 있습니다.
2) 큰 슬래브를 data
개 할당하고 한 번에 하나씩 돌리면 도움이됩니다.
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 바이트 지역은 일부 메모리를 저장 :이 작업을 위해, 우리는 빈 생성자 및 "setvalues"방법이 필요합니다. 위의 코드는 완전한 코드가 아니며 "어떻게 수행 할 수 있는지 보여주는"것입니다.
3) 멀티 맵에서 "키"가 어디에서 왔는지 여전히 확실하지 않지만 키가 value1 및 value2 항목 중 하나 인 경우 다른 사본을 저장하는 대신 키 중 하나를 다시 사용할 수 있습니다 [ 그것이 현재 어떻게되고 있는지 가정 해 보자.
이것이 진정한 대답이 아닌 경우 유감이지만 '내가하고있는 일에 대한 설명에 어딘가에서 설명되지 않은 것'이라는 의미에서 대답이라고 생각합니다.
프로그램에서 어떤 할당이 이루어 졌는지 이해하면 분명 도움이 될 것입니다.
플라이급 디자인 패턴을 사용해 보셨습니까? – Deamonpog
[부스트 플랫 연관 컨테이너] (http://www.boost.org/doc/libs/1_53_0/doc/html/container/non_standard_containers.html#container.non_standard_containers.flat_xxx)를 살펴볼 수 있습니다. 물론 삽입에 대한 성능상의 상충 관계가 있습니다. – juanchopanza
외부 라이브러리를 사용하고 싶지 않습니다. 내 프로젝트 지침에 따라, 나는 C++ 표준 라이브러리를 사용해야한다. – Manish