Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Pierrick's Blog

.Net "full power"

C# : Vérifications / Performances

Lorsque que l'on écrit une méthode, il est d' usage de vérifier les paramètres...

mais quelle méthode employez vous ?

la méthode simple, le strict minimum  ?

private static void MyMethod1(string a, string b, string c, string d)
{
   
if (a == null)
       
throw new ArgumentNullException(string.Format(Properties.Resources.EX_1, "a"), (Exception)null);
   
if (b == null)
       
throw new ArgumentNullException(string.Format(Properties.Resources.EX_1, "b"), (Exception)null);
   
if (c == null)
       
throw new ArgumentNullException(string.Format(Properties.Resources.EX_1, "c"), (Exception)null);
   
if (d == null)
       
throw new ArgumentNullException(string.Format(Properties.Resources.EX_1, "d"), (Exception)null);
}

Ou une méthode plus élégante  ? (il y a plus d' informations pour l' appelant lors d' une exception)

private static void MyMethod2(string a, string b, string c, string d)
{
   
ArgumentNotNull(a, Properties.Resources.EX_1, "a");
   
ArgumentNotNull(b, Properties.Resources.EX_1, "b");
   
ArgumentNotNull(c, Properties.Resources.EX_1, "c");
   
ArgumentNotNull(d, Properties.Resources.EX_1, "d");
}

Check.ArgumentNoNull vaut :

public static void ArgumentNotNull(object obj, string fmt, params object[] args)
{
   
if (obj == null)
       
throw new ArgumentNullException(string.Format(fmt, args), (Exception)null);
}

Certes plus élégante, mais elle est malheureusement plus lente à l' exécution. Au premier coup d' oeil, on s' aperçoit qu' à chaque appel, "Properties.Resources.EX_1" est évaluée !

Comparons tout de même :

int nb = 10000;
TimeSpan t1 = DoTest(MyMethod1, nb);
TimeSpan t2 = DoTest(MyMethod2, nb);
Console.WriteLine("t1 : {0}, t2:{1}, t2/t1:{2}", t1, t2, t2.TotalMilliseconds / t1.TotalMilliseconds);

Résultat :

image 

Les chiffres sont petits, mais le nombres d'appels n' est que de 10 000. Le rapport est accablant la deuxième méthode est 86 fois plus lente !!!!!

l' idée ici est gardé un code élégant, tout en se rapprochant des performances de  'MyMethod1'.

Comment évaluer "Properties.Resources.EX_1" uniquement lorsque l' argument est null ?

il suffit de déléguer....

private static void MyMethod2_1(string a, string b, string c, string d)
{
    ArgumentNotNull(a, () => ThrowNull(Properties.
Resources.EX_1, "a"));
    ArgumentNotNull(b, () => ThrowNull(Properties.
Resources.EX_1, "b"));
    ArgumentNotNull(c, () => ThrowNull(Properties.
Resources.EX_1, "c"));
    ArgumentNotNull(d, () => ThrowNull(Properties.
Resources.EX_1, "d"));
}

public static void ThrowNull(string fmt, params object[] args)
{
   
throw new ArgumentNullException(string.Format(fmt, args), (Exception)null);
}

public static void ArgumentNotNull(object obj, Action OnNullAction)
{
   
if (obj == null)
        OnNullAction();
}

et en utilisant les méthodes d' extensions on arrive à quelque chose du genre

private static void MyMethod3(string a, string b, string c, string d)
{
    a.IsNull(() => ThrowNull(Properties.
Resources.EX_1, "a"));
    b.IsNull(() => ThrowNull(Properties.
Resources.EX_1, "b"));
    c.IsNull(() => ThrowNull(Properties.
Resources.EX_1, "c"));
    d.IsNull(() => ThrowNull(Properties.
Resources.EX_1, "d"));
}

et IsNull ressemble beaucoup à ArgumentNotNull

public static void IsNull(this object value, Action OnNullAction)
{
   
if (value == null)
        OnNullAction();
}

on pourrait encore enlever ThrowNull

private static void MyMethod4(string a, string b, string c, string d)
{
    a.IsNull(() => Properties.
Resources.EX_1, "a");
    b.IsNull(() => Properties.
Resources.EX_1, "b");
    c.IsNull(() => Properties.
Resources.EX_1, "c");
    d.IsNull(() => Properties.
Resources.EX_1, "d");
}

 

et les performances ???

image 

en conclusion pour 1 000 000 d' appels, la méthode la moins coûteuse dans les plus élégantes, est la méthode 3

private static void MyMethod3(string a, string b, string c, string d)
{
    a.IsNull(() => ThrowNull(Properties.
Resources.EX_1, "a"));
    b.IsNull(() => ThrowNull(Properties.
Resources.EX_1, "b"));
    c.IsNull(() => ThrowNull(Properties.
Resources.EX_1, "c"));
    d.IsNull(() => ThrowNull(Properties.
Resources.EX_1, "d"));
}

1 000 000 d'appels  () :

  1. Methode 1 : 17.7 ms
  2. Méthode 3 : 44.2 ms

Contexte du Test :

  • Portable Core 2 Duo, 2Ghz, 2Go de RAM
  • .Net 3.5 (sans le sp1)
  • Windows Vista sp1
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: vendredi 29 août 2008 16:59 par pierrick

Commentaires

Julien237 a dit :

Merci pour ces tests !

C'est intéressant de voir les résultats, mais aussi de voir comment les autres font...

Au niveau du debuggage, on remarquera que seule la première méthode présente un StackTrace correct :

La dernière méthode appelée sera bien celle dans laquelle l'erreur s'est produite (ou peut-être son appelant dans la cas d'un ArgumentNullException).

Si le debuggage doit être fait par d'autres personnes cela peut être un peu perturbant...

Personnellement j'utilise un snippet, code final peu élégant, mais pas long à taper pour autant...

# août 29, 2008 19:00

cyril a dit :

premiere méthode pour moi aussi.

A noter que ton cas est un parfait scénario pour l'utilisation de l'AOP (Programmation Orienté Aspect). Parmis ceux que j'ai utilisé pour .net mon préféré est http://www.postsharp.org/

# août 30, 2008 13:28

simon ferquel a dit :

Ahhhh le bon vieux temps des macros :p

# août 30, 2008 16:20

smo a dit :

Quand on se pose se genre de questions de base, le mieux c'est de regarder dans le framework .NET lui-même, et dans 99% des cas, on aura

void MyMethod1(string a)

{

   if (a == null)

       throw new ArgumentNullException("a");(string.Format(Properties.Resources.EX_1, "a"), (Exception)null

# août 31, 2008 16:00

smo a dit :

OOPS mon précédent post à fourché :) je voulais dire:

void MyMethod1(string a)

{

   if (a == null)

       throw new ArgumentNullException("a");

   ...

}

On remarquera d'ailleurs que FXCop (=Code Analyzer) vérifie celà sous cette forme.

# août 31, 2008 16:02
Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- [Refactoring] ReSharper pour Visual Studio 2010 (Preview) par Thomas Jaskula le il y a 1 heure et 1 minutes

- [Refactoring] Analyser vos exceptions avec ReSharper Exceptional par Thomas Jaskula le il y a 2 heures et 15 minutes

- SharePoint 2007 : patterns & practices SharePoint Guidance par Philippe Sentenac [MVP SharePoint] le il y a 15 heures et 55 minutes

- [Visual Studio 2010] Les tests cases c’est bien, mais je vais devoir tout réécrire ? par Etienne Margraff le il y a 16 heures et 51 minutes

- MVP[Gribouillon].AddYear par The Grib's Lair [Sébastien PICAMELOT - MVP SharePoint] le il y a 17 heures et 6 minutes

- Clinique INSIA - Projet de fin d’Etudes (Silverlight 3 MVVM et OutOfBrowser, WCF, TFS) - Part 1 par David REI le 07-02-2009, 23:38

- C’est la crise ? Bah pourquoi cramer du budget pub alors ? par Nix's Blog le 07-02-2009, 15:31

- Soyons MVP ! par TheSaib .NET blog le 07-02-2009, 12:15

- SharePoint : Gestion des Erreurs 6398, 7076 et 6482 par Blog Technique de Romelard Fabrice le 07-02-2009, 11:53

- EF avec WPF par Matthieu MEZIL le 07-02-2009, 10:18