2017-02-15 35 views
3

Это действительно уродливый вопрос.Смягчение утечек памяти путем разветвления

У меня есть программа C++, которая делает следующее в цикле:

  • ждет сообщения JMS
  • Рассчитывает некоторые данные
  • Посылает сообщение JMS в ответ

Мои программа (назовем ее «Боб») имеет довольно сильную утечку памяти. Утечка памяти находится в общей библиотеке, которую кто-то написал, которую я должен использовать, но исходный код, к которому у меня нет доступа.

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

Из-за различных ограничений (да, это проблема X/Y, я сказал вам, что это было некрасиво), я решил, что моя единственная жизнеспособная стратегия заключается в том, чтобы модифицировать Боба так, чтобы он выполнял следующее в своем цикле:

  • Ждет сообщения JMS
  • Рассчитывает некоторые данные
  • посылает сообщение JMS в ответ
  • Проверяет, является ли она в опасности использования «слишком много» памяти
  • Если да, вилки и исполняет ругой копировать себя и изящно выходит

Мой вопрос заключается в следующем:

Что является лучшим (надежным, но не слишком неэффективно) способ обнаружить ли мы с помощью «слишком много» памяти? Моя текущая мысль состоит в том, чтобы сравнить getrlimit(RLIMIT_AS) rlim_cur с getrusage(RUSAGE_SELF) ru_maxrss; это верно? Если нет, то что лучше? Боб работает в виртуальной машине Linux на разных хост-машинах, все с разным объемом памяти.

+4

Предполагая, что утечка памяти происходит на фазе «Вычисляет некоторые данные», мне интересно, будет ли иметь смысл просто реорганизовать эту часть в отдельную программу и выполнить вилку для ее выполнения в отдельном пространстве памяти. Таким образом, вы можете, по крайней мере, изолировать оскорбительный код и упростить его замену в будущем, а не просто маскировать проблему, перезагрузив программу, когда она будет работать с низким объемом памяти. Это просто мысль - не видя кода, я не могу сказать, является ли это жизнеспособным вариантом для вас. –

+2

в качестве обходного пути; почему бы не выходить каждый раз, когда выполняется вычисление, и перезапускать программу каждый раз? –

+0

Джин, в крайнем конце, который жизнеспособен. Мне интересно, можно ли сократить накладные расходы, только перезагрузившись, когда это необходимо. – Arandur

ответ

1

Предполагая, что утечка памяти происходит на фазе «Вычисляет некоторые данные», я думаю, что имеет смысл просто реорганизовать эту часть в отдельную программу и развернуть ее, чтобы выполнить ее в своем собственном процессе. Таким образом, вы можете, по крайней мере, изолировать оскорбительный код и упростить его замену в будущем, а не просто маскировать проблему, перезагрузив программу, когда она будет работать с низким объемом памяти.

Часть «Вычисляет некоторые данные» может быть долговременным процессом, который ждет запросов от основной программы и при необходимости перезагружается, или (даже проще), это может быть одноразовая программа, которая просто берет свои данные в *argv и отправляет свои результаты в stdout. Тогда ваша основная петля может просто разветвиться и выполнить ее каждый раз и прочитать результаты, когда они вернутся. Я пошёл бы с более простым вариантом, если это возможно, но это, конечно, будет зависеть от ваших потребностей.

0

Если вы запустите программу или перезапустите раздел «Вычисляет некоторые данные» на отдельный процесс, в любом случае вам нужно будет проверить потребление памяти. Поскольку вы находитесь в Linux, простой способ проверить это - получить номер pid интересующего процесса и прочитать содержимое файла /proc/$PID/statm. Второй номер - это размер резидентного набора.

Чтение этих файлов proc - это то, как инструменты, такие как top и htop, получают данные о процессах. Периодически считывать 30-байтовый файл в памяти, чтобы проверить утечку памяти, не кажется слишком неэффективным.

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