У меня есть внутреннее приложение C ++, которое будет расти бесконечно — настолько, что нам пришлось реализовать логику, которая фактически убивает его, когда RSS достигает определенного пикового размера (2,0 ГБ), просто чтобы поддерживать некоторое подобие порядка. Тем не менее, это показало некоторые странные поведения.
Сначала я запустил приложение через Valgrind с помощью memcheck и исправил некоторые случайные утечки памяти здесь и там. Однако степень утечек памяти измерялась в десятках мегабайт. Это имеет смысл, поскольку может случиться так, что в действительности утечки памяти не будет — это может быть просто плохое управление памятью на стороне приложения.
Затем я использовал Valgrind с массивом, чтобы проверить, куда идет память, и вот тут-то и странно. Снимок пика составляет 161M — нигде рядом с пиками 1.9G + мы не видим, используя поле RSS. Наибольшее потребление я бы ожидал — в std :: string — но это не ненормально.
Наконец, и это самое удивительное: до того, как мы узнали об этой утечке памяти, я на самом деле тестировал этот сервис на AWS и просто для удовольствия установил большое число рабочих на машине с CC2.8XL, 44 работников. Это 60,5 ГБ ОЗУ, и без подкачки. Перенесемся на месяц вперед: я иду, чтобы посмотреть на хост — и низкий, и вот, он исчерпан на оперативной памяти — НО! Процессы по-прежнему работают нормально и застряли на разных этапах использования памяти — почти равномерно распределены от 800M до 1.9G. Время от времени dmesg
выдает ошибку Xen о невозможности выделить память, но, кроме этого, процессы никогда не умирают и продолжают активно обрабатывать (то есть они не «застряли»).
Есть что-то, чего я здесь не хватает? В основном это работает, но я не могу понять почему. Что было бы хорошей рекомендацией о том, что искать дальше? Есть ли инструменты, которые могут помочь мне разобраться?
Обратите внимание, что valgrind memcheck обнаруживает только когда вы «покидаете» память. while(1) vec.push_back(n++);
заполнит всю доступную память, но не сообщит о любых утечках. Судя по звукам вещей, вы где-то собираете строки, которые занимают много места. Я также работал над кодом, который использует много памяти, но на самом деле она не утекает [все в разных местах, что Вальгринд счастлив, а не утечка!]. Иногда вы можете отследить это, просто добавив некоторые маркеры в выделение памяти или что-то подобное, чтобы указать, ГДЕ вы выделяете память.
В std::
функции, как правило, есть Allocator
аргумент. Если вы реализуете несколько разных пулов памяти, вы можете найти, где вы выделяете память.
Я также видел случаи, когда я думаю, что процесс имеет фрагментированную память, поэтому в куче много свободного места — это может произойти, если, например, вы создаете много строк, добавляя к размеру строка.
Других решений пока нет …