5 votes

L'application ASP.NET consomme de la mémoire. Les objets d'application / de session en sont-ils la cause ?

Nous testons donc une application ASP.NET développée par une société externe. Nous recevons environ 50 requêtes par seconde et, après une demi-heure, chacun des 48 processus de travail (w3wp.exe) a atteint environ 400 Mo et plus. Le système fonctionne sous IIS7.

Après avoir manipulé dotTrace, je suis presque certain qu'il y a une fuite de mémoire, mais il est difficile d'en être sûr à 100% sans connaître l'application. Lorsque nous avons confronté les développeurs à cette théorie, ils l'ont rejetée après 30 secondes en disant quelque chose comme "la mémoire est gérée automatiquement dans .NET". .NET aurait certainement collecté 48x~400MB s'il s'agissait de données finalisées ?

De toute façon, j'ai l'habitude de travailler avec WinForms. Comment exactement créer des fuites de mémoire en ASP.NET ? Le seul moyen est-il d'utiliser (mal) les objets Application et Session dans .NET ?

modifier

Depuis que j'ai posté cette question, j'ai appris que le fait de conserver des références statiques à des objets dans les gestionnaires de requêtes (qu'il s'agisse d'une classe de service Web, d'un formulaire Web ou autre) entraîne des "fuites". Ce n'est probablement pas le terme exact, mais bon... Je n'étais pas sûr de cela, car je pensais que les classes de gestionnaires étaient détruites et recréées après chaque requête par IIS.

Alors codez comme ceci :

public class SomeService : IService
{
    public static List<RequestData> _requestDataHistory = new List<RequestData>();
    public void SomeRequest(RequestData data)
    { 
        _requestDataHistory.Add(data);
    }        
}

fera planter votre serveur tôt ou tard. Peut-être que cela était évident pour la plupart des gens, mais pas pour moi :-)

Je ne sais toujours pas si cela poserait un problème si vous supprimiez le mot-clé statique. Est-ce que instances éliminé après chaque demande ?

2voto

Paul Roub Points 11185

Les développeurs pourraient avoir raison. Dans le monde .Net, le ramassage des ordures et la libération de la mémoire se font en cas de besoin. C'est-à-dire que si l'application dispose de beaucoup de mémoire, elle peut en consommer de plus en plus, jusqu'à ce que le système d'exploitation ne permette plus d'allocation. Vous ne devriez pas vous inquiéter de cela, sauf si cela pose vraiment des problèmes.

Bien sûr, il peut y avoir des fuites de mémoire, si l'application ne dispose pas correctement des ressources non gérées, comme les sockets, les gestionnaires de fichiers, etc. Regardez les objets du système d'exploitation (dans le gestionnaire de tâches, vous pouvez activer les colonnes handles et user objects) pour voir comment ils se développent.

Comme vous l'avez dit, une mauvaise utilisation de l'objet Application ou Session peut également être une cause.

Je me demande pourquoi vous auriez 48 pools d'applications (processus de travail). C'est une surcharge, et vous n'en avez absolument pas besoin.

Le GC gère la mémoire par processus, et 400MB par processus, ce n'est pas beaucoup du tout. Réduisez le nombre de pools d'applications au nombre de cœurs - 1, puis testez l'application. Si elle se développe trop, vous pouvez craindre des fuites de mémoire.

D'après vos informations complémentaires, oui, dans ce cas, la liste d'historique s'allongera indéfiniment. Les objets statiques sont créés une fois par domaine d'application, et vivent jusqu'à ce que le domaine d'application vive.

Je ne vous conseille pas de supprimer arbitrairement le mot-clé static, à moins que vous ne soyez sûr de ne pas casser une certaine logique d'application. Cherchez à savoir pourquoi ces données sont collectées de toute façon, et à quoi elles servent. Le code a également un autre problème - il n'est pas thread safe, son comportement est indéfini lorsque 2 requêtes arrivent en même temps, et décident d'ajouter des données à cette liste.

Mieux vaut déplacer votre question vers stackoverflow.com, car il s'agit d'une question de programmation, et non d'administration.

Si vous n'avez pas le contrôle de ce code, et que vous voulez vraiment résoudre votre problème de mémoire, vous pouvez configurer vos pools d'applications pour qu'ils se recyclent après un nombre X de requêtes, ou après avoir obtenu plus de Y quantité de mémoire - mais encore une fois, ce n'est pas une vraie solution.

0 votes

Cela pose des problèmes. Les processus de travail finissent par planter parce qu'ils n'ont plus de mémoire lorsqu'ils essaient d'en allouer davantage. Je suis d'accord sur le fait que 400MB seul n'est pas beaucoup, mais 400*48 MB l'est. Si nous réduisons à un seul processus de travail, il utilisera finalement la même quantité de mémoire que les 48 combinés (bien que cela n'ait pas été testé, je n'ai pas le pouvoir de le faire).

0 votes

S'il vous plaît, vérifiez mon édition

0 votes

Merci pour votre contribution. Je suppose que le problème s'est transformé en une question de programmation, oui. Je ne contrôle pas le code. En attendant de trouver une solution, nous utiliserons la technique de recyclage - merci !

0voto

user48838 Points 7385

Les fuites de mémoire, au sens général, sont les résultats négatifs/imprévus d'une logique de codage qui ne libère pas correctement (ou pas du tout) ses ressources inutilisées (ou qui ne sont plus utilisées) tout en réservant des ressources supplémentaires pour des besoins nouveaux/continus d'utilisation/de traitement. L'"empreinte" globale des ressources continue alors de croître, même si les besoins réels n'augmentent pas nécessairement si le "nettoyage" approprié de l'utilisation et de la libération correctes des ressources est en place.

En bref, il ne se limite pas à un "abus" de programmation logique, mais peut provenir d'hypothèses incorrectes de gestion des ressources ou simplement de leur absence.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X