Как я могу найти утечку памяти на Heroku?

У меня есть приложение Rails 3.2.8, работающее на кедре Heroku с Ruby 1.9.3. Приложение отлично работает при запуске, но через день или около того непрерывного использования я начинаю видеть ошибки R14 в своих журналах. Как только ошибки памяти начинаются, они никогда не уходят, даже если приложение простаивает в течение нескольких часов.

не должен ли сборщик мусора очистить неиспользуемые объекты через некоторое время и уменьшить нагрузку на память? Кажется, это происходит не на Heroku. Как правило, использование памяти начинает ползти вверх после запуска некоторые отчеты с несколькими тысячами строк данных, хотя результаты разбиты на страницы.

Как я могу найти утечку памяти? Плагины, такие как bleak_house, устарели или не работают в среде Heroku. Могу ли я настроить параметры GC, чтобы сделать его более агрессивным?

2 ответов


GC должен сделать очистку, и, вероятно, делает.

вы можете заставить GC с GC.start; если многие объекты не были собраны, это будет, но я подозреваю, что это не проблема.

возможно ли, что вы каким-то образом создаете кучу объектов и никогда не выпускаете их, сохраняя кэшированные копии или что-то еще?

Я не знаком с существующими инструментами для проверки этого, но вы можете проверить, какие объекты существуют с помощью ObjectSpace. Для пример:

ObjectSpace.each_object.with_object(Hash.new(0)){|obj, h| h[obj.class] +=1 }
# => a Hash with the number of objects by class

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


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

некоторые из приятных функций, которые включает New Relic, могут точно определить источник самого длинного SQL-запроса, например. Я призываю вас попробовать.