Отладка утечки памяти в sidekiq с помощью jemalloc

Итак, у меня утечка памяти в моем рабочем в Sidekiq. У меня есть рабочий сервер с одной очередью только для этой рабочей задачи, которая получает около 10 ГБ RSS в неделю.

Я попытался воспроизвести его локально, используя только 1 рабочий поток и вуаля - я получаю от 200M до 1G за одну ночь, обрабатывая 1 задание в минуту. Естественно, я хочу знать, что происходит, поэтому я также веду журнал RSS, heap_live_slots и heap_free_slots. Когда я отображаю результаты, я вижу устойчивый рост RSS, в то время как живые и свободные слоты колеблются случайно, но в четко определенных и постоянных границах, в то время как их сумма остается постоянной.

На этом этапе я прихожу к выводу, что утечка, вероятно, происходит не в коде Ruby, а скорее в каком-то родном расширении. Поэтому я переустанавливаю ruby ​​с поддержкой Jemalloc через RVM:rvm reinstall 2.4.2 --with-jemalloc

Затем я настроил MALLOC_CONF:

export MALLOC_CONF='prof_leak:true,lg_prof_sample:0,prof_final:true,stats_print:true'

И запустить Sidekiq. Недавно запущенный Sidekiq с 1 рабочим потоком стоит около 200M RSS, но когда я нажимаю Ctrl+C и смотрю статистические данные jemalloc, я вижу нечто совершенно иное:

Arenas: 32
Quantum size: 16
Page size: 4096
Maximum thread-cached size class: 32768
Allocated: 34056, active: 61440, metadata: 2949272, resident: 2981888, mapped: 6352896, retained: 2035712

Какие? 6М сопоставлены? Это не может быть правдой. Поэтому я запускаю irb и делаю следующее:

2.4.2 :001 > arr = []
 => [] 
2.4.2 :002 > loop do
2.4.2 :003 >   arr << 'a'*10000000
2.4.2 :004?>   sleep 1
2.4.2 :005?> end

После ожидания, пока процесс irb не поднимется до 1G RSS, я останавливаю процесс... и вижу точно такие же числа. Может быть, визуализация графика звонков поможет мне понять, что происходит?

jeprof --show_bytes --pdf `which ruby` jeprof.10536.0.f.heap > ruby.pdf

Using local file /home/mhi/.rvm/rubies/ruby-2.4.2/bin/ruby.
Using local file jeprof.10536.0.f.heap.
No nodes to print

Так что что-то явно не так, и вот что мне нужно, чтобы выяснить.

Вот полный вывод статистики jemalloc: https://pastebin.com/RiMLtqA6

UPD.

Итак, я обновил все гемы, связанные с нативным расширением, вот выводbundle exec ruby -e 'puts Gem.loaded_specs.values.select{ |i| !i.extensions.empty? }.map{ |i| "#{i.name} #{i.version}" }':

io-console 0.4.6
nokogiri 1.8.1
bcrypt 3.1.11
debug_inspector 0.0.3
binding_of_caller 0.7.2
json 2.1.0
capybara-webkit 1.14.0
damerau-levenshtein 1.3.0
unf_ext 0.0.7.4
eventmachine 1.2.5
ffi 1.9.18
kgio 2.11.0
msgpack 1.1.0
mysql2 0.4.9
rainbow 2.2.2
raindrops 0.18.0
rbtrace 0.4.8
stackprof 0.2.10
therubyracer 0.12.3
unicode 0.4.4.4
unicorn 5.3.0

Тот же результат: RSS, Слоты памяти

1 ответ

В Ruby 2.4.2 есть известная проблема сjemalloc,

проблема была закрыта около месяца назад, но я не знаю, пропатчен ли используемый вами пакет... На самом деле, я не думаю, что патч был выпущен. Это, вероятно, все jemalloc данные статистики не имеют значения.

Кроме того, это похоже на вопрос XY (вы спрашиваете о jemalloc, в то время как вы, вероятно, хотите решение проблемы утечки памяти).

Прежде чем предположить утечку памяти в нативном коде (хотя это явная возможность), я хотел бы рассмотреть, как область действия задачи может повлиять на сборщик мусора, и попытаться минимизировать как область действия, так и любые переменные с длительным сроком службы.

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

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

Другие вопросы по тегам