Программа работает по итерациям. В пределах одной итерации, заполняются некоторые структуры данных. Используется STL (string, map, vector и т. п.). Также используются потоки (пул из n штук по количеству ядер, каждый обрабатывает, как правило, по 1/n части какого-нибудь map-а). Между итерациями все основные структуры уничтожаются (остаётся небольшой объём данных). Как правило, между итерациями, размер RSS (используемой физической памяти) и VIRT (размер адресного пространства) не уменьшается или уменьшается очень незначительно. В некоторых случаях удавалось добиться, чтобы память отдавалась ОС, но я пока не разобрался, что на это влияет. Получается, что размер используемой памяти остаётся равным максимальному размеру, который требуется для одной итерации. Дело происходит под Linux (Ubuntu), amd64, gcc 4.3.
Вопросы:
— почему так происходит; в каких случаях, вообще, память должна возвращаться системе? (вариант с перезапуском программы не рассматриваем);
— можно ли добиться ожидаемого результата, если использовать другие аллокаторы (которые заменяют malloc), если да — то какие?
— можно ли добиться ожидаемого результата, если использовать другие аллокаторы для STL, если да, то какие, и в какие контейнеры их стоит ставить?
Re: Как сделать, чтобы память возвращалась системе?
Здравствуйте, Аноним, Вы писали:
А>- можно ли добиться ожидаемого результата, если использовать другие аллокаторы для STL, если да, то какие, и в какие контейнеры их стоит ставить?
Ну как вариант — можно работать через mmap/munmap и pool allocator...
Здравствуйте, Аноним, Вы писали:
А>Вопросы: А>- почему так происходит; в каких случаях, вообще, память должна возвращаться системе? (вариант с перезапуском программы не рассматриваем);
От стандартного аллокатора она возвращается только если кусок был получен достаточно большой (по умолчанию это, кажется, 64K). В этом случае выделение происходит mmap'ом. В противном случае, выделение делается через [s]brk() и назад оно не отдаётся.
Поэтому для таких заведомо уничтожаемых данных нужен свой аллокатор. Через что будет тот получать память — уже менее важный вопрос.
А>- можно ли добиться ожидаемого результата, если использовать другие аллокаторы (которые заменяют malloc), если да — то какие?
Это вряд ли, потому что нужно точное указание для каждого объекта, к какому пулу он относится.
А>- можно ли добиться ожидаемого результата, если использовать другие аллокаторы для STL, если да, то какие, и в какие контейнеры их стоит ставить?
Да, это путь реальный. Точных названий не скажу — не копал. Но аллокатор такого рода должен работать следующим образом:
* получать память от системы через mmap()
* распределять своими средствами
Если в процессе обработки одной карты нет массовых уничтожений, то можно сделать предельно тупо — аллокатор просто получает кусок и последовательно выделяет из него, не строя никаких структур учёта, а delete() у него — просто NOP. По концу обработки карты даётся команда "очистить" и вся память освобождается через munmap(). Получается что-то вроде GC, только по группам.
Проблемы могут быть с тем распределением памяти, которое программисту неизвестно. Например, если делать мьютекс на каждый объект, то будет занят приличный кусок стандартного пула. (Но это обычно плохой метод — если делать мьютексы, то группами по hash-id объекта; а вообще синхронизацию в таких задачах надо продумывать очень серьёзно и отдельно). В любом случае, перед уничтожением пула крайне желательно выполнить все штатные деструкторы участвовавших объектов и только после этого отбрасывать память, которая была под пулом.
The God is real, unless declared integer.
Re: Как сделать, чтобы память возвращалась системе?