Как заставить мою std:: map освобождать используемую память?

Я использую std:: map, и я не могу освободить память обратно в ОС. Похоже,

int main(){
  aMap m;

  while(keepGoing){
    while(fillUpMap){
       //populate m
    }
    doWhatIwantWithMap(m);
    m.clear();//doesnt free memory back to OS

    //flush some buffered values into map for next iteration
    flushIntoMap(m);
  }
}

Каждый (fillUpmap) выделяет около 1gig, поэтому я очень заинтересован в том, чтобы вернуть его в свою систему, прежде чем он поглотит всю мою память.

Ive испытал то же самое с std::vector, но там я мог заставить его освободиться, выполнив обмен с пустым std::vector. Это не работает с картой.

Когда я использую valgrind, он говорит, что вся память освобождена, поэтому это не проблема с утечкой, так как после прогона все хорошо очищается.

изменить:

Сброс должен появиться после очистки.

Ответ 1

m.clear() освобождает память обратно в кучу, но для реализации кучи не рекомендуется выводить обратно обратно в ОС (даже если это возможно, такие проблемы, как фрагментация, затрудняют).

Так работает распределитель по умолчанию, если вы указали свой собственный распределитель для карты, он может иметь свой собственный кеш. Однако даже в этом случае он должен быть кэширован, чтобы в любом случае повторно использовать его.

Карты не имеют понятия емкости и размера, как это делают векторы.

Ответ 2

Это поведение нормальное, библиотека времени выполнения сохраняет память, выделенную классом карты, доступной для процесса, так что в следующий раз, когда ему нужно выделить память, ему не нужно идти в операционную систему. Это оптимизация библиотеки времени выполнения.

Ответ 3

Если вы создадите карту в куче (через новую), ее удаление освободит любую используемую память.

Ответ 4

Я проделал простой тест, когда я поместил некоторые данные в std:: map и затем вызвал std:: map:: clear().

typedef std::map<int, unit_t,std::less<int>,  
     my_allocator<std::pair<const int, unit_t>, 4 > > contaner_t;
contaner_t keys;
keys[1] = 10;
keys[2] = 20;
keys[3] = 30;
keys.clear();

это результат ввода printf в мой тест:

Allocator # 4, Memory consumption:      56     (allocated   :       56)
Allocator # 4, Memory consumption:     112     (allocated   :       56)
Allocator # 4, Memory consumption:     168     (allocated   :       56)
Allocator # 4, Memory consumption:     112     (deallocated :       56),
Allocator # 4, Memory consumption:      56     (deallocated :       56),
Allocator # 4, Memory consumption:       0     (deallocated :       56),

Я думаю, вам, вероятно, также следует проверить поведение распределителя, но я думаю, что ваш стандартный std:: allocator по умолчанию освобождает память, как вы ожидаете, но эта память не возвращается в ОС. Кстати, какую ОС вы используете?

Вопрос в том, как вы измеряете can't seem to free the memory back to the OS. и как вы можете быть уверены, что I could force it to free by doing a swap with an empty std::vector. Вы действительно уверены, что выделенная память фактически возвращается к ОС?

Ответ 5

Возможно, вы могли бы создать собственный распределитель или просто использовать библиотеку пула Boost.

Ответ 6

Сменить трюк? Я знаю, что вы делаете это с помощью векторов и т.п., Но я сделал это с картами раньше.

Ответ 7

Я полагаю, вы работаете в Linux.

Если вам действительно нужно минимизировать объем памяти вашего приложения, вы можете вызвать malloc_trim() после очистки карты. Я бы также порекомендовал взглянуть на manlopt() manpage - там есть некоторые подсказки о том, почему ваш код может сохранять память, а не возвращать ее в ОС.