Я использую MIC для своего LRU-кэша на сервере, он заменил LRU list / map, так как я подозревал, что именно это вызвало необъяснимый след памяти. Утечки памяти не видны, по крайней мере, ни один инструмент не обнаружил утечек, а также проверку кода. С тех пор, как я начал использовать MIC, картина улучшилась (это единственное доказательство фрагментации памяти), но этого недостаточно. Мы говорим о нескольких гигабайтах кеша, миллионы записей извлекаются из него ежедневно. Через две-три недели проблема становится очевидной — если я очищаю кэш, процесс все еще держит необъяснимые 2-3 ГБ памяти.
Мой контейнер довольно прост:
typedef std::pair<Key, T> Element;
typedef mic::multi_index_container<
Element,
mic::indexed_by<mic::sequenced<mic::tag<struct Seq>>,
mic::hashed_unique<mic::tag<struct Hash>, mic::member<Element, const Key, &Element::first>>>>
item_list;
оно использует erase
а также push_front
вставить новую запись (или перезаписать старую), а затем, если необходимо, извлечь элемент из tail. Вопрос стоит ли пытаться использовать replace
а также relocate
вместо push_front
?
UPDATE001: Хорошо, новая версия запущена и работает, я вижу, что realocate значительно улучшил ситуацию, объем памяти после 3 недель был меньше, чем объем памяти на машинах без изменений. Теперь он развернут на всех машинах по всему миру. Второй этап — многочисленные изменения в механизме аннулирования кэша. Меньшее количество выбрасываний и повторных вставок также должно улучшить ситуацию (если это действительно фрагментация памяти)
Мы пережили то же самое.
Я написал небольшую тестовую программу, которая использует наш кэш из 300 потоков. Это держит insert
и erase
примерно 200k (вставка + стирание) / сек, и я запустил его на выходных.
Я проверил использование памяти через pmap -x всего RSS
pmap -x [pid] | tail -n1 | awk '{print $4}'
В одноминутном разрешении видно, что до загрузки кеша потребление памяти ~ линейно от 0 до 4,7 ГБ, а после этого оно увеличивается с логарифмической скоростью. Как показано на рисунке. (Потребовалось 14 минут, чтобы заполнить кеш).
Еще одна интересная вещь заключается в том, что pmap -x сообщил о загрузке большого количества 65536 тыс. Порций виртуальной памяти (так что может быть теоретический максимум для такого чрезмерного использования памяти), но если я проделал то же самое из одного потока, тестовая программа выделил один блок размером 4,7 ГБ, и после того, как кэш был заполнен, использование памяти было постоянным.
Других решений пока нет …