Bloat RSS et fragmentation mémoire glibc sur workers Python

Posté par zgaillard le 16/04/2026
RÉSOLU

zgaillard

Membre depuis le 16/11/2024

hello. on a un souci de fuite mémoire sur nos workers python en prod. l'appli tourne sur debian bullseye. le RSS monte linéairement jusqu'au OOM-kill du pod sans jamais redescendre même après un cycle GC complet.

on a déjà checké avec tracemalloc et objgraph. l'heap python est stable. le souci semble être au niveau de l'allocateur système. c'est une horreur à debugger.

Commentaires

cohen-laurent

Membre depuis le 31/01/2025

classique. glibc et les threads python ça fait pas bon ménage sur la gestion des arènes. par défaut glibc crée jusqu'à 8 arènes par cœur cpu. ça fragmente à mort.

t'as essayé de limiter les arènes avec une variable d'environnement ?

zgaillard

Membre depuis le 16/11/2024

j'ai testé ça ce matin sans grand succès :

export MALLOC_ARENA_MAX=2

le RSS monte moins vite mais ça finit toujours par péter. j'ai l'impression que la mémoire est jamais rendue à l'OS.

ilacroix

Membre depuis le 01/06/2019

actif

regarde tes smaps. faut voir si t'as beaucoup de trous dans les mappings. fais un dump de /proc/PID/smaps_rollups pour voir l'état global.

zgaillard

Membre depuis le 16/11/2024

voilà le retour du rollup :

Rss: 1245672 kB
Pss: 1210432 kB
Shared_Clean: 512 kB
Shared_Dirty: 0 kB
Private_Clean: 124 kB
Private_Dirty: 1245036 kB
Referenced: 1245672 kB
Anonymous: 1245012 kB
LazyFree: 0 kB
AnonHugePages: 0 kB
ShmemPmdMapped: 0 kB
Shared_Hugetlb: 0 kB
Private_Hugetlb: 0 kB
Swap: 0 kB
SwapPss: 0 kB
Locked: 0 kB

presque tout est en private dirty. c'est pas du leak de lib externe on dirait.

cohen-laurent

Membre depuis le 31/01/2025

si ton heap python est stable c'est forcément la glibc qui retient les pages. elle utilise brk() ou mmap() pour tes allocs ?

si c'est du brk() et que t'as un objet long-lived tout en haut du tas ça bloque toute la libération en dessous.

zgaillard

Membre depuis le 16/11/2024

on a pas mal de petits objets qui restent en cache (LRU). ça doit être ça qui fait chier. comment je force glibc à être plus agressive sur le free ?

ilacroix

Membre depuis le 01/06/2019

actif

tu peux pas vraiment. glibc est naze pour ça. passe sur jemalloc ou mimalloc. jemalloc gère vachement mieux la fragmentation sur les long-running processes.

fais un test rapide en injectant la lib via LD_PRELOAD dans ton container.

zgaillard

Membre depuis le 16/11/2024

je vais tenter jemalloc. faut que je l'installe dans mon dockerfile d'abord. t'as une config spécifique pour les dirty pages ?

cohen-laurent

Membre depuis le 31/01/2025

ajoute ça pour que jemalloc rende la mémoire plus vite :

MALLOC_CONF="dirty_decay_ms:1000,muzzy_decay_ms:1000"

ilacroix

Membre depuis le 01/06/2019

actif

installe le paquet libjemalloc2. dans ton dockerfile :

RUN apt-get update && apt-get install -y libjemalloc2
ENV LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libjemalloc.so.2"

zgaillard

Membre depuis le 16/11/2024

c'est en prod sur un noeud de test. j'observe le graph prometheus là. la courbe est radicalement différente. le RSS reste plat après la phase de warmup.

cohen-laurent

Membre depuis le 31/01/2025

check quand même tes latences. jemalloc peut rajouter un peu d'overhead sur les allocs très fréquentes mais normalement sur du python ça se voit pas.

zgaillard

Membre depuis le 16/11/2024

les p99 ont pas bougé. par contre la conso ram est passée de 1.2GB à 450MB stable. glibc nous volait 800MB de ghost memory par worker.

ilacroix

Membre depuis le 01/06/2019

actif

c'est classique sur les runtimes asynchrones ou multithreadés. glibc garde les pages au cas où pour la perf mais ça finit en carnage sur k8s.

zgaillard

Membre depuis le 16/11/2024

incroyable. j'ai passé tout le cluster sous jemalloc. plus aucun OOM sur les 4 dernières heures. merci les gars pour le coup de main sur l'allocateur c'était pile ça.

Laisser une réponse

Vous devez être connecté pour poster un message !

Rejoindre la communauté

Recevoir les derniers articles gratuitement en créant un compte !

S'inscrire