Astuces DotNet (Sébastien Courtois)

28/01/2010

[.NET] Le mot clé sealed sur une classe permet-il permettre de gagner en performance ?

Filed under: .NET, Débutant, Intermediaire, Optimisation — Étiquettes : , , , , , — sebastiencourtois @ 00:19

Voici la question que Wilfried Woivre (MSP ainsi que “Ask The Expert” sur Azure aux prochains Tech Days 2010).

Ma première réponse a été… “J’en sais rien”🙂. En effet, le mot clé sealed a toujours été, pour moi, utilisé pour des design OO spécifiques (type création de framework public …) où l’idée est d’interdire l’extension d’une classe (la fonction première du mot clé sealed). J’ai donc dit que je pensais que ce n’était pas le cas ni le rôle de ce mot clé.

Quelque temps plus tard, je me retrouve à lire un chapitre sur l’optimisation de code .NET dans lequel le mot clé “sealed” == performance. J’ai donc décidé de faire le benchmark suivant :

   public class ClassA
   {
       public void Method1() { }
   }

   public sealed class ClassASealed
   {
       public void Method1() { }
   }

   public class ClassAVirtual
   {
       public virtual void Method1() { }
   }

    
class Program
{
    static void Main(string[] args)
    {
        ClassA ca = new ClassA();
        ClassASealed cas = new ClassASealed();
        ClassAVirtual cav = new ClassAVirtual();

        Stopwatch swca = new Stopwatch();
        Stopwatch swcas = new Stopwatch();
        Stopwatch swcav = new Stopwatch();
        for (int i = 0; i < 10000000; i++)
        {
            swca.Start();
            ca.Method1();
            swca.Stop();

            swcas.Start();
            cas.Method1();
            swcas.Stop();

            swcav.Start();
            cav.Method1();
            swcav.Stop();
        }

        Console.WriteLine("ClassA  : " + swca.Elapsed);
        Console.WriteLine("ClassAS : " + swcas.Elapsed);
        Console.WriteLine("ClassAV : " + swcav.Elapsed);
        Console.WriteLine("Finish");
        Console.ReadLine();
    }
}

On teste, ici, le temps d’appel des méthodes en faisant 1 000 000 d’appels. On trouve les résultats suivants :

  • Classe Normale : 22.8844652 secondes
  • Classe Sealed : 22.8523417 secondes
  • Classe Normale avec une méthode virtuelle : 23.0062174 secondes

Premier constat : Le mot clé sealed nous permet de gagner environ 1 pour 1000 en performance.

Deuxième constat : la méthode virtuelle semble faire perdre aussi des performances ( 5 ou 6 pour 1000).

Pourquoi ces écarts ?

1°)Parlons tous d’abord de l’écart normale/sealed : Au niveau du code IL, il n’y a que le sealed de différence :

.class public auto ansi beforefieldinit ClassAVirtual
.class public auto ansi sealed beforefieldinit ClassASealed

L’optimisation à lieu au niveau du Runtime. En effet, sachant que la classe est scellé, le runtime peut faire un appel direct à la méthode (dans certains cas, exécuter le code sans faire d’appel).

2°) Pour la différence méthode classique /méthode virtuelle :

.method public hidebysig instance void Method1() cil managed
.method public hidebysig newslot virtual instance void Method1() cil managed

Le virtual ici oblige le runtime a créer une table d’appel pour cette méthode virtuelle dans laquelle seront contenu les méthodes des classes dérivées qui surchargeront cette méthode. Par conséquent, un appel à cette méthode est un appel ‘virtuel’ de méthode qui doit aller chercher dans cette table pour trouver la bonne méthode à appelé. Même si dans notre cas, la table ne contient qu’un seul élément, il y a tout de même un coût supplémentaire par rapport à un appel classique (accès à la table,recherche dans la table …)

Conclusion

Effectivement, le fait de mettre rendre classe ‘sealed’ permet de gagner des performances. Toutefois les performances sont tellement faible que dans 95 % des cas (disons : les applications non temps réel ou ne travaillant pas avec des énormes volumes de données), ces gains sont négligeables et il sera plus judicieux de voir s’il n’y a pas des optimisations à faire au niveau du code ou de l’architecture du projet.

Laisser un commentaire »

Aucun commentaire pour l’instant.

RSS feed for comments on this post. TrackBack URI

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

Propulsé par WordPress.com.

%d blogueurs aiment cette page :