Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

The Mit's Blog

En plus d'intégrer et skier, il sait même écrire !
(Blog de Renaud Comte)

Actualités

Gestion du Dispose : Attention au Memory Pressure sous SharePoint (et donc comment faire mieux)

Un post qui vient un poil en doublon de ceux qui relaye 2 nouveaux articles de blog mais ces posts sont vraiment mais vraiment de premier choix :

J'ai donc décider d'en faire une petite relecture et en français pour changer

Ces 2 articles viennent décortiquer en profondeur la problématique de libération des objets contextuels de SharePoint tels que les fameux SPWeb et le SPSite. Et quand je dis décortiquer, je ne joue pas sur les mots.

Stefan Gossner descend très bas dans le fonctionnement même du ramasse miettes du framework et donc explique les conséquences négatives de certaines "façons de faire" de nos amis les développeurs s ASP.Net

Roger Lamb, lui, a tout simplement passé son temps à explorer le comportement du framework sous SharePoint avec WinDbg. En pratique, tester et évaluer toutes les situations d'utilisation des SPWeb et leurs réels impacts

Évidemment, la lecture de ces posts implique 2-3 petites choses :

Pour avoir eu récemment cette discussion avec diverses personnes lors des TechDays, il s'agit surtout d'accepter de remettre en question de vilaines habitudes de programmation au profit d'autre.

Surtout d'accepter de mieux appréhender et comprendre son code au dépit de simplement enchaîner des ForEach et des Current.Site à tout vas.
>>> Je sais, il est facile de dire qu'il faut coder plus propre, se remettre en question et de pondérer ses choix mais quand on est en situation de production, de livraison, de projet difficile, La tentation d'aller au plus vite peut être bien grande.

Le seul soucis est que certains problèmes ne surgissent que sous une vraie montée en charge d'un serveur, de vrais conditions de production ou de volumétrie
>>> sous entendu, indétectable en VPC local

Malheureusement, lorsque ces soucis de performance arrive, la reprise de code est souvent trop tardive et vraiment couteuse.

Pourquoi de tels impacts dans le cas de SharePoint ?
>>> Simple :

  1. Les projets types Portails, Ged ou Collaboratifs brassent forcement de grand volume de data et de nombreux utilisateurs
  2. Les objets SharePoint sont bien plus lourds que les classes de bases, ils représentent un systéme complet avec des notions de contexte et de dépendances sur différents objets comme du COM par exemple ...

Reprenons donc par le début et les posts suivants :

Le problème en question n'est pas relatif à une fuite mémoire mais plus trop à un phénomène de "trop peu" en ASP.Net aka "memory pressure".

En ASP.Net, le processus est embarqué dans le worker process w3wp.exe et il se cumule avec les DLL d'IIS comme les filtres et extensions ISAPI. L'adressage de la mémoire virtuelle avec .Net fonctionnant avec des jalons de 64 MB (soit 2GB max sous 32 bits). Hors, si le framework n'arrive pas à trouver des segments continues d'au moins 64MB bien le phénomène de "memory pressure" apparaît

==> Conséquence :

  • le Garbage Collector est activé de plus en plus fréquemment
  • instabilité du processus mémoire inhérent
  • montée en CPU
  • Erreurs "Out of memory"

Que de malheur en perspective non ?

A priori, le "memory pressure" est souvent constaté autour de charges de 800/1000 MB

Soit les leçons les plus importantes (et souvent bien connus et malheureusement ignorés )

  • le mode Debug fragmente réellement la mémoire du fait que chaque page est compilé dans une dll différentes
    >>> privilégier le mode Release !
     
  • Si vos objets contiennent des ressources non managés (donc hors du contrôle du framework), seul la méthode Close() ou Dispose() peuvent réellement libérer leur espace mémoire. Sinon, seul le "finalizer" en dernier recours s'en occupera (et souvent un peu trop tardivement)
    >>> Comme le SPWeb/SPSite utilisent l'objet SPRequest en interne qui lui référence bien des objets COM non managés, il est d'autant plus important de bien fermer/libérer ces fameux objets (Best Practices: Using Disposable Windows SharePoint Services Objects )
     
  • Si vos applications Web partagent tous le même le pool applicatif, elles partagent le même worker process donc ... il faut mieux répartir en fonction du besoin les couples application/pool
     
  • Il est quand même bien conseillé de ne pas trop ouvrir d'objets SPWeb en continue. Simple vous me dirait, mais des fois, c'est un comportement caché de certains contrôles comme le provider de navigation qui si il doit énumérer plus de 5 niveaux de sous site vas travailler comme un fou ...

La conclusion de Stefan Gossner est donc logique et très intéressantes

Un fois la théorie comprise, le post plus concret de Roger Lamb prend tout son  intérêt en testant les différent patterns d'ouverture de SPWeb/SPSite

Il y a d'abord quelques bons points à toujours se rappeler

  • les objets qui ont des références COM sont plus facilement libérables si ils sont fait dans le même cycle d'opération. Ce n'est pas le ca quand une méthode les ouvre et une autre les libére
  • le "memory pressure" et autre "memory leaks" apparaissent surtout dans les opérations récursives (comme la navigation par exemple) ou les items receivers
  • Attention, les objets SPWeb/SPSite ne doivent pas être libérés si ils sont utilisés dans le processus de rendu de la page principal (dixit le probléme de close des objets Web dans une WebPart). Par contre de nombreux objets ont souvent des propriétés méconnues qui eux chargent des référence internes à des objets SPWeb/SPSite et eux doivent être libérer !

Voici quelques exemples de ma sélection personnelle, comme :

  • Le fameux SPSite (surtout ouvert en ligne)
using (SPWeb web = new SPSite(SPContext.Current.Web.Url).OpenWeb())
{
  // SPSite leaked! 
}
  • Le non moins fameux SPWeb
using (SPWeb outerWeb = siteCollection.OpenWeb())
{
   using (SPWeb parentWeb = outerWeb.ParentWeb) // Internal reference to SPWeb parentWeb
   {
   string sTitle = parentWeb.Title;
   string sUrl = parentWeb.Url;
   } // SPWeb object parentWeb.Dispose() automatically called
} 
  • SPControl et SPContext ne doivent pas utiliser de Dispose !
    Soit :
SPSite siteCollection = SPContext.Current.Site;
SPWeb web = SPContext.Current.Web;
// Do NOT call Dispose()

using (SPWeb webRoot = SPContext.Current.Site.OpenWeb())
{
  // SPSite is ok since it came from SPContext and      
  // this is a fairly common pattern to keep an eye out for
}
  • SPLimitedWebPartManager
using (SPLimitedWebPartManager webPartManager = page.GetLimitedWebPartManager(PersonalizationScope.Shared))
{
      webPartManager.Web.Dispose();
}
  • PublishingWeb
foreach (PublishingWeb innerPubWeb in pubWebCollection)
{
    innerPubWeb.Close();
}
  • La propriété Owner du SPSite
using (SPSite siteCollection = new SPSite("http://moss"))
{
   SPUser ownerUser = siteCollection.Owner;
   siteCollection.RootWeb.Dispose();
} 
  • L'indexeur AllWeb
using (SPWeb outerWeb = siteCollection.OpenWeb())
{
   foreach (SPWeb innerWeb in siteCollection.AllWebs)
  {
      innerWeb.Dispose();
   }
} // SPWeb object outerWeb.Dispose() automatically called

ainsi que
using (SPWeb web = siteCollection.AllWebs.Add("site-relative URL"))
{
} // SPWeb object web.Dispose() automatically called
  • SPSiteCollection[]
SPWebApplication webApp = new SPSite("http://moss").WebApplication;
SPSiteCollection siteCollections = webApp.Sites;

foreach (SPSite siteCollection in siteCollections)

{
   siteCollection.Dispose();
}

La liste est encore plus longue sur le post d'origine, je ne peut que vous conseiller sa lecture complète !

Ce post atteignant certainement les records de longueurs de mes posts, je n'oserais continuer plus loin cette analyse/traduction personnel des posts d'origine si ce n'est de vous conseiller de :

  1. Bien lire ces fameux posts !
  2. Faire bien attention à votre code et comprendre le risque de celui ci
  3. pondérer précipitation, productivité et performance dans vos développements
  4. relire en profondeur

Bon coding à tous

Renaud Comte aka TheMit (comment ça mes posts sont trop courts ?)
Member of WygTeam
http://www.wygwam.com

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :
Posted: lundi 25 février 2008 16:19 par themit

Commentaires

Pas de commentaires

Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Technofolies, votre évènement numérique de l'année par Le Blog (Vert) d'Arnaud JUND le 09-26-2014, 18:40

- Xamarin : From Zero to Hero par Fathi Bellahcene le 09-24-2014, 17:35

- Conférences d’Automne 2014 par Le blog de Patrick [MVP SharePoint] le 09-24-2014, 14:53

- [TFS] Supprimer un projet de Visual Studio Online par Blog de Jérémy Jeanson le 09-22-2014, 20:42

- Nouveau blog en anglais / New blog in english ! par Le blog de Patrick [MVP SharePoint] le 09-18-2014, 18:42

- [ #Yammer ] From Mailbox to Yammer and back / De votre messagerie vers Yammer et retour ! par Le blog de Patrick [MVP SharePoint] le 09-15-2014, 11:31

- [ #Office 365 ] New service settings panel / Nouveau panneau de paramétrage des services par Le blog de Patrick [MVP SharePoint] le 09-11-2014, 08:50

- Problème de déploiement pour une démo SharePoint/TFS? par Blog de Jérémy Jeanson le 09-10-2014, 21:52

- [ #Office365 ] Delve first impressions / Premières impressions sur Delve par Le blog de Patrick [MVP SharePoint] le 09-09-2014, 16:57

- [ #Office365 ] How to change Administration console language ? / Comment changer la langue de la console d’administration ? par Le blog de Patrick [MVP SharePoint] le 09-09-2014, 08:25