LINUX.ORG.RU

Прошу помощи в продвижении баги Glibc: free не освобождает часть памяти

 , , , ,


1

4

Есть в Glibc особенность, описанная [1] во времена царя гороха.

Если я правильно понимаю, это является причиной многих ситуаций, когда у приложений «течет память». И почему-то я никогда не встречал пояснения, что это by design благодаря... Glibc! Пока сам не столкнулся: я аналитик (но был программистом), и у меня в Pandas тупо сжирается вся память даже после сборки мусора.

Так вот, по сути. Есть такой mallopt-параметр, M_MXFAST [2]. Он задает порог размера блока (я сейчас пересказываю, возможно несоответствие действительности), меньше которого не происходит реальное освобождение блока памяти при вызове free. Заметим, кстати, что по умолчанию этот параметр никак не 0 (а 64*sizeof(size_t)/4).

Так вот, при повторных вызовах free аккумуляции значения, которое сравнивается с порогом, не происходит. То есть, аллоцировав [3] миллион раз 64 байта, а затем миллион раз ее освободив, мы получим 64 мебибайта текущего использования памяти.

Память освобождается только в случае вызова malloc_trim(). Ну, или, отключения всей этой оптимизации: mallopt(M_MXFAST, 0).

Понятно, что каждый разработчик может выбрать один из двух вариантов, но, де-факто, я предполагаю, что мало кто об этом задумывается. Там же [1] отмечают, что «в KDE это порождает утечки 600Mb». И, собственно, предлагают, аккумулировать количество и/или общий размер неосвобожденных таким образом блоков. Или, хотя бы, ввести переменную окружения по аналогии с MALLOC_TRIM_THRESHOLD_ [2].

Но за 6 лет даже не разрослась дискуссия. А, кажется, место многих проблем-то! Может, хоть знать бы об этом хорошо? Вот разработчики Pandas, кажется, не знают: [4], [5]. (Мне кто-то подсказал в том треде, разработчики не заметили. И привлекать внимание не хочется закроют по WONTFIX и все.) Я понимаю - закрой рот и напиши патч, всё такое. Но думаю, стоит достучаться до тех, кто разбирается в коде Glibc. И в его подходах.

Подскажите, как быть? И прав ли я в утверждении о том, что надо что-то делать? :)

P.S. Хотя, с другой стороны, [6].

---

напиши функции-обёртки для malloc и free и сам там аккумулируй и дёргай trim. думаю, что в библиотеке это аккумулирование просто никому не нужно. потому что многопоточность и нафиг не нужно лочить ресурсы на каждый чих.

Iron_Bug ★★★★ ()

1. Ты путаешь теплое с мягким.

2. Pandas должен обращаться к glibc только в случае если сам Python скомпилен в отладочном режиме. Если это происходит «всегда» то я бы стал это рассматривать как баг Pandas а не glibc.

cvv ★★★★★ ()

Да, было бы неплохо это исправить. Чем дольше работает приложение, тем больше памяти так утечёт маленькими кусочками (хотя может trim вызовется по другим причинам и подберёт их).

Как workaround можно запускать этот pandas с jemalloc или другим альтернативным аллокатором.

Вот разработчики Pandas, кажется, не знают

Они же там отписались и закрыли с wontfix, просто уже забыли.

xaizek ★★★★★ ()
Последнее исправление: xaizek (всего исправлений: 1)

Если я правильно понимаю, это является причиной многих ситуаций, когда у приложений «течет память».

Не совсем, это задокументированное поведение. Скорее это можно описать как «так исторически сложилось».

меньше которого не происходит реальное освобождение блока памяти при вызове free

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

Но за 6 лет даже не разрослась дискуссия. А, кажется, место многих проблем-то! Может, хоть знать бы об этом хорошо?

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

Подскажите, как быть? И прав ли я в утверждении о том, что надо что-то делать? :)

Прав, нужно рассказать разработчикам Pandas про madvise.

xpahos ★★★★★ ()

добро пожаловать в реальный мир

http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/stdlib/malloc.c

посмотри что с ним стало, с самой первой нижней до самой последней верхней

и этот маллок всеравно не кросплатформеннен и течет на всем что отлично от x86

и твое открытие для начало надо протестировать на хотяб нескольких поддерживаемых Glibc процессорах(даже одной архитектуры) чтоб понять локальный он для «дной затычки» или нет(вероятность99.9% что это одна затычка под твой проц такая, или еще какая локальная проблема в ядре)

missxu ()
Ответ на: комментарий от kuraga

У Питона есть свой собственный аллокатор и скорее всего подобные модули должны обращаться именно к нему.

Хотя, если честно, я уже давно не писал питоновских модулей

cvv ★★★★★ ()

На самом деле нет. При дефолтных настройках блоки памяти агрегируются, то есть будет зааллоцировано из имеющегося пула. По факту malloc использует mmap по мере надобности и добавляет к пулу. Но эти все механизмы можно сломать кривыми ручками и получить переполнение памяти мелкими блоками. Но даже это сложно сделать при включенном overcommit'е, так как память физически мапится только когда начинает использоваться. Можно переполнить таблицу мапов, конечно, но это надо хотеть делать специально, и это тоже непросто.

slapin ★★★★★ ()

Можно написать preload враппер, который при первом обращении к malloc устанавливает нужные опции.

Можно посмотреть в сторону всяких (tc|je|.*)malloc и их опций.

Кмк, от стандартных аллокаторов отказываются все более менее взлетевшие проекты, со временем. Так что, прежде чем ковырять треккер libc надо бы проверить, тем же ltrace'om как работает выделение памяти в интересующем ПО.

pon4ik ★★★★★ ()

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

vtVitus ★★★★★ ()