none
LocalReport.Render et Nb Handles GC (Perfmon) qui augmentent indéfiniment RRS feed

  • Question

  • Bonjour,

     

    J'utilise l'exemple de code issu du http://msdn.microsoft.com/fr-fr/library/ms252091.aspx pour imprimer des rapport RDLC sans passer par un aperçu (dans un service NT écrit en C#).

     

    Tout fonctionne bien ... sauf qu'en testant mon service sur plusieurs impressions pour vérifier toute dérive mémoire éventuelle (avec performance monitor), je remarque que le Nombre de Handle GC (Mémoire CLR.NET\Nb handles GC dans perfmon) augmente sans jamais redescendre (y compris après plusieurs heures sans activité).

     

    A première vue, si je n'appelle pas la méthode LocalReport.Render, le nombre de handle GC reste stable.

     

    Je ne comprends pas trop le soucis et donc comment y remédier. J'ai peur qu'une fois mon service en production, le serveur soit saturé après quelques jours d'utilisations.

     

    Avre vous des idées/pistes sur le sujet ?

     

    Merci d'avance.

    François.

     

    mardi 12 août 2008 10:04

Réponses

  • Bonjour,

     

    Il y a un défaut de conception dans votre code du main.

     

    En fait lorsque vous appelez la méthode Run() :

    • Une tableau de flux mémoire est crée.
    • La méthode Export() est appellée et créer autant de flux fichier qu'il y a de page (un handle en interne est donc crée)

    La méthode Demo.Dispose() qui libère ces flux créer est appellée une fois (lors de la sortie du bloc using).

     

    Le problème ici, c'est que vous utilisez le même objet Demo qui stocke tous les flux de toutes vos pages que vous imprimez.

     

    Pour corrigez ce problème il faut créer et  un objet démo

     

    Code Snippet

    public static void Main(string[] args)
    {
        Console.WriteLine("Enter for begin");
        Console.ReadLine();

        for (int i = 0; i < 10; i++)
        {
            using (Demo demo = new Demo())
            {
                demo.Run();
            }
        }

        Console.WriteLine("Enter for end");
        Console.ReadLine();
    }

     

    Ainsi, vous libérez à chaque itération les flux des pages crée (et qui ne sont plus nécessaires).

     

    Cordialement

    vendredi 22 août 2008 10:33
    Modérateur

Toutes les réponses

  • Bonjour,

     

    Ce comportement peut être tout à fait normal car le déclenchement du GC de .NET est non prévisible... Cela dépend de la pluie et du beau temps ainsi que de l'humeur de Windows...

     

    Avez-vous essayez de tester la montée en charge d'un autre programme pour voir si l'utilisation de la mémoire de votre service redescend ?

    Est-il possible de voir le code d'impression autour de LocalReport.Render() ?

     

    Cordialement

     

    vendredi 15 août 2008 12:24
    Modérateur
  • Bonjour,

     

    Le code que j'utilise est exactement celui donné dans http://msdn.microsoft.com/fr-fr/library/ms252091.aspx.

     

    En faisant un exe de type console et en modifiant le Main comme ci-dessous, on voit facilement avec "perfmon" la montée du nombre de handles du GC sans jamais voir le compteur descendre, sauf quand le process est stoppé (vous pouvez attendre plus d'une heure, le compteur ne bouge pas ...).

     

    Code Snippet

    public static void Main(string[] args)

    {

      using (Demo demo = new Demo())

      {

        Console.WriteLine("Enter for begin");

        Console.ReadLine();

        for (int i = 0; i < 10; i++)

        {

          demo.Run();

        }

        Console.WriteLine("Enter for end");

        Console.ReadLine();

      }

    }

     

    Dans le méthode "Run", vous pouvez mettre l'appel à la méthode "Print" en commentaire pour ne pas avoir l'impression finale (ne change rien sur le comportement du nombre de handle du GC).

     

    Merci d'avance pour votre aide.

    François.

    jeudi 21 août 2008 09:46
  • Bonjour,

     

    Il y a un défaut de conception dans votre code du main.

     

    En fait lorsque vous appelez la méthode Run() :

    • Une tableau de flux mémoire est crée.
    • La méthode Export() est appellée et créer autant de flux fichier qu'il y a de page (un handle en interne est donc crée)

    La méthode Demo.Dispose() qui libère ces flux créer est appellée une fois (lors de la sortie du bloc using).

     

    Le problème ici, c'est que vous utilisez le même objet Demo qui stocke tous les flux de toutes vos pages que vous imprimez.

     

    Pour corrigez ce problème il faut créer et  un objet démo

     

    Code Snippet

    public static void Main(string[] args)
    {
        Console.WriteLine("Enter for begin");
        Console.ReadLine();

        for (int i = 0; i < 10; i++)
        {
            using (Demo demo = new Demo())
            {
                demo.Run();
            }
        }

        Console.WriteLine("Enter for end");
        Console.ReadLine();
    }

     

    Ainsi, vous libérez à chaque itération les flux des pages crée (et qui ne sont plus nécessaires).

     

    Cordialement

    vendredi 22 août 2008 10:33
    Modérateur
  • OK, je vais modifier mon code pour créer un objet à chaque impression et voir si le nombre de handle GC baisse.

    Je vous tiens au courant.

    Merci.

    mercredi 27 août 2008 15:21