Устранение утечки памяти рабочих сторон sidekiq с помощью jemalloc

Итак, у меня утечка памяти у моего работника 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, Слоты памяти

Ответ 1

Ruby 2.4.2 имеет известную проблему с jemalloc.

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

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

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

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

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