2 votes

Écrire des millions d'enregistrements dans une table mnesia consomme beaucoup de mémoire (RAM) et ne libère pas cette mémoire même si ces enregistrements sont supprimés.

Je gère une application Erlang qui écrit souvent des millions d'enregistrements dans la table mnesia pour créer une planification. Lorsque l'heure est venue, les enregistrements sont exécutés et supprimés de la table. La table est configurée avec {type, disk_copies}, {type, ordered_set}. J'utilise des opérations de transaction pour l'écriture et des opérations dirty pour supprimer les enregistrements.

J'ai fait une expérience qui écrit 2 millions d'enregistrements puis les supprime tous : la mémoire RAM n'a pas été récupérée une fois l'opération terminée. Il y a un pic qui double la mémoire lorsque je commence à supprimer ces enregistrements. Par exemple, la mémoire beam commence à 75 Mo, et après l'expérience elle passe à 410 Mo. J'ai utilisé erlang:memory() pour inspecter la mémoire avant et après, j'ai trouvé que la mémoire était consommée par les process_used et binary mais en réalité, je n'ai effectué aucune action avec binary. Si j'utilise erlang:garbage_collect(Pid) pour tous les processus en cours d'exécution, la mémoire est récupérée, ne laissant que 180 Mo.

Toute suggestion pour résoudre ce problème serait grandement appréciée. Merci beaucoup.

1voto

tandathuynh148 Points 87

Réponse de Rickard Green d'Elrang OTP :

Le ci-dessus ne signifie pas un bug.

Un processus n'est pas collecté par le garbage collector à moins qu'il n'atteigne certaines limites, par exemple, il doit allouer des données de heap et il n'y a pas de heap libre disponible. Si un processus cesse d'exécuter, peu importe le temps qui passe, il ne se collectera pas automatiquement par lui-même sauf s'il atteint l'une de ces limites. Une collecte de garbage peut être forcée en appelant erlang:garbage_collect() cependant.

Un processus qui a eu beaucoup de données vivantes (et par cela a augmenté en taille) mais au moment de la collecte de garbage n'a pas de données vivantes ne rétrécira pas immédiatement à sa taille initiale. Il obtiendra plutôt un heap relativement grand. L'espace du heap est libre pour l'utilisation par le processus, mais il est alloué du point de vue du système. Le heap relativement grand est sélectionné afin d'éviter de déclencher des collectes de garbage inutilement fréquentes.

Non seulement vos processus sont affectés lorsque vous exécutez. D'autres processus peuvent également accumuler du heap pour servir vos processus.

Si vous regardez la consommation mémoire via top ou similaire, il est également prévu que l'utilisation de mémoire aura augmenté après l'exécution même si vous êtes en mesure de collecter par le garbage tous les processus à leur taille initiale. Cela est dû aux allocateurs de mémoire qui placent des blocs de mémoire dans des morceaux de mémoire plus grands qui ne peuvent pas être supprimés jusqu'à ce que le morceau de mémoire entier soit libre. Plus ou moins tous les systèmes d'allocation de mémoire qui existent auront cette caractéristique.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X