Comme je commençais à accumuler pas mal de liens intéressants sur la gestion de la mémoire, je me suis décidé à écrire un article. J'espère qu'il vous sera utile, au moins pour la culture générale.

Multithreading et malloc()

L'implémentation actuelle du célèbre allocateur de mémoire malloc() de la GNU libc est peu performante pour un programme multi-threadé. En particulier, la mémoire se fragmente facilement et l'allocation de mémoire est donc de plus en plus lente. Google a développé sa propre version de malloc() : tcmalloc. Elle est disponible dans la suite google-perftools sous la nouvelle licence BSD. Côté points noirs, tcmalloc utilise directement 6 Mo au démarrage pour son usage interne, et elle ne rend jamais la mémoire au système !

La prochaine version de FreeBSD (7.0) aura aussi un nouvel allocateur de mémoire : jemalloc, écrit par Jason Evans. L'implémentation actuelle de de FreeBSD est celle de Poul-Henning Kamp : phkmalloc. Vous trouverez une présentation de jemalloc dans l'article What's cooking for FreeBSD 7? Lisez également le papier écrit par Jason en avril 2006 : A Scalable Concurrent malloc Implementation for FreeBSD.

Selon un benchmark « NetBSD versus FreeBSD », les performances restent stables au delà de 4 threads (sur une machine ayant 4 processeurs) pour le nouvel allocateur de FreeBSD, alors que pour NetBSD et Linux les performances s'écroulent. En utilisant tcmalloc, les performances de Linux sont similaires à celle de FreeBSD.

La version actuelle de la GNU libc utilise ptmalloc2, implémentation inspiré de celle de Doug Lea (dlmalloc) version 2.7. La nouvelle glibc (version 2.6) utilise ptmalloc3 : 3e version de ptmalloc, basée sur dlmalloc 2.8.3 (date de 2005).

Mesure de la mémoire des processus

En avril 2007, Matt Mackall présentait son travail sur la quantification de la mémoire utilisée par un processus au Embedded Linux Conference. Il part du constat que les valeurs données par le noyau Linux n'ont que pas/peu de sens.

Il propose un patch pour le noyau qui permet de compter le nombre de processus partageant une page mémoire. La quantité de mémoire utilisée par un processus est alors le nombre de pages mémoire non partagées plus le nombre de pages partagées divisé par le nombre d'utilisations. Exemple : si 20 programmes utilisent une bibliothèque KDE de 30 Mo, la bibliothèque pèsera 30/20 = 1,5 Mo pour chaque processus et non plus 30 Mo comme c'est le cas actuellement ! Ceci permettra d'avoir une meilleure idée de la répartition de la mémoire. LWN.net propose un article détaillant la présentation de Matt.

Aux dernières nouvelles (voir les prévisions météo de Linux), le patch devrait être intégré dans Linux 2.6.25. La dernière version stable de Linux est la 2.6.23 et la 2.6.24 est en cours de développement. Il faudra être donc être encore un peu patient (ou alors recompiler son noyau à la main ;-)).

Astuce : Pour mesurer l'utilisation de la mémoire vidéo par les applications graphiques, utilisez le programme xrestop plutôt que top ;-)

Ce que tous les programmeurs doivent savoir au sujet de la mémoire

Ulrich Drepper, actuel mainteneur de la GNU libc travaillant pour RedHat, a écrit un article détaillant sur 100 pages la mémoire de nos jours (2007) : What every programmer should know about memory. Il a contacté le site Internet LWN.net pour publier son article. Pour une lecture plus confortable, l'article est découpé en 6 parties :

J'ai commencé à lire la 1ère partie qui est d'une excellente qualité. Par contre, c'est extrêmement technique et très détaillé. La première partie présente l'organisation logique d'un ordinateur en se concentrant sur le/les processeurs, la mémoire, le northbridge et le southbridge. Merci à toady de m'avoir indiqué ce lien ;-)

Noyau Linux

Le site linux-mm.org (Linux Memory Management) centralise les informations sur la gestion de mémoire par le noyau Linux. On y trouve les projets en cours de développement comme advanced page replacement. On y trouve aussi de très bonnes informations sur le gestionnaire de mémoire Linux, comme par exemple les articles OOM Killer (mécanisme qui désigne quel processus tuer quand la machine n'a vraiment plus de mémoire) et page fault handling. Rik van Riel a d'ailleurs publié une lettre ouverte invitant les universités à faire de la recherche fondamentale sur la gestion de la mémoire. Les algorithmes utilisés ne sont plus adaptés aux machines actuelles !

Et Python ?

Le gestionnaire de mémoire interne de Python 2.3 et 2.4, pymalloc, est bogué. Il ne rend jamais la mémoire au système ! Lisez le billet d'Evan Jones pour en savoir plus. Evan Jones a justement corrigé ce bug et son travail a été intégré dans Python 2.5. Lisez l'annonce d'Evan Jones et l'annonce de Tim Peters sur la liste de diffusion python-dev. Tim Peters a repris le travail d'Evan Jones, l'a corrigé et l'a intégré à Python.

Pour finir, voici deux outils permettant de tracer l'utilisation de la mémoire : PySizer et Heapy. Je ne les ai pas encore testé, mais ils sont certainement très instructifs. Lisez également le papier Heapy: A Memory Profiler and Debugger for Python.

N'oubliez pas d'utiliser régulièrement Valgrind sur vos programmes pour traquer les fuites de mémoire !