Итак, у меня утечка памяти у моего работника Sidekiq. У меня есть рабочий сервер с одной очередью только для этой рабочей задачи, который получает около 10G RSS в неделю.
Я попытался воспроизвести его локально только с одним рабочим потоком и вуалой - я получаю от 200 М до 1Г за одну ночь, обрабатывая 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
Что? 6M отображается? Это не может быть правдой. Поэтому я запускаю 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 stat: 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, Слоты памяти