Minimiser l’empreinte mémoire dans les programmes C

Quelles sont mes options pour minimiser l’encombrement mémoire dans les programmes C sous Linux (* nix)?

Pour autant que je sache, libc malloc () utilise soit brk () soit mmap (). La mémoire allouée avec brk () ne peut généralement pas être renvoyée en raison de la fragmentation de la mémoire.

Mon programme devrait fonctionner 24/7 et il fait beaucoup de malloc () – s et free () – s. Après avoir démarré, RSS atteint environ 100 Mo. C’est trop, car je suis certain que, à un moment donné, il y a moins de 100 Mo de données en mémoire.

C’est probablement le problème de fragmentation brk ().

Alors, quelles sont mes options ici?

Dois-je utiliser une autre implémentation de malloc (), qui utilise uniquement mmap ()? Devrais-je faire autre chose? Y a-t-il quelque chose que je puisse lire concernant le problème de l’empreinte mémoire?

Merci.

Si votre programme a tellement d’appels malloc et free appels free que vous obtenez ce type de fragmentation, l’utilisation de mmap pour chaque allocation sera désespérément lente. Au lieu de cela, vous devez mesurer ce qui cause la fragmentation de la mémoire et y remédier. D’abord, j’utiliserais un outil comme valgrind pour m’assurer qu’il ne s’agit pas réellement d’un problème de fuite / corruption de la mémoire provoquant une utilisation excessive de la mémoire. Ensuite, pour confirmer que la cause du problème est la fragmentation, j’emballerais tous les appels dans malloc et free avec votre propre wrapper qui incrémenterait et décrémenterait une variable “total des octets alloués” afin que vous puissiez, à tout moment, comparer les valeurs théoriques et consommation de mémoire réelle.

S’il s’avère que la fragmentation est le problème, une bonne première étape consiste à déterminer pourquoi vous faites tant de petites allocations de courte durée. Si vous pouvez les éliminer et allouer à la place toute la mémoire dont un object de tâche / données particulier aura besoin dans un seul bloc, alors vous devez vous débarrasser de la plus grande fragmentation, mais aussi améliorer les performances de votre code. un peu. Chaque appel à malloc ou free entraîne un peu de surcharge, en particulier dans un environnement threadé où la synchronisation / le locking est nécessaire. Conserver toutes les données associées dans un seul bloc alloué peut également réduire ou éliminer le besoin d’écrire un code spécial sur des structures libres contenant des pointeurs; un seul appel à free peut souvent suffire (bien que pour que l’implémentation rest opaque, vous devez toujours envelopper une fonction foo_free ).

Sauf si vous allouez des blocs de taille fixe – ou effectuez une collecte périodique des ordures ménagères -, votre empreinte mémoire risque de dépasser les besoins en raison de la fragmentation.

free() ne peut pas renvoyer de mémoire à l’OS à moins que les pages complètes ne soient pas utilisées.

Ma suggestion serait d’utiliser un schéma d’ allocation de la dalle . Pré-allouer plusieurs pools de mémoire. Chaque pool sera utilisé avec des objects de taille similaire (taille idéalement identique). De cette façon, vous évitez la fragmentation et gardez votre empreinte RSS constante (même si elle est plus importante que nécessaire en raison de la préallocation).