142 votes

Performances des méthodes statiques par rapport aux méthodes d'instance

Ma question porte sur les caractéristiques de performance des méthodes statiques par rapport aux méthodes d'instance et sur leur évolutivité. Supposons pour ce scénario que toutes les définitions de classe se trouvent dans un seul assemblage et que plusieurs types de pointeurs discrets sont nécessaires.

Pensez-y :

public sealed class InstanceClass
{
      public int DoOperation1(string input)
      {
          // Some operation.
      }

      public int DoOperation2(string input)
      {
          // Some operation.
      }

      // … more instance methods.
}

public static class StaticClass
{
      public static int DoOperation1(string input)
      {
          // Some operation.
      }

      public static int DoOperation2(string input)
      {
          // Some operation.
      }

      // … more static methods.
}

Les classes ci-dessus représentent un modèle de style "helper".

Dans une classe d'instance, la résolution de la méthode d'instance prend un certain temps, contrairement à une classe statique.

Mes questions sont les suivantes :

  1. Lorsque la conservation de l'état n'est pas une préoccupation (aucun champ ou propriété n'est requis), est-il toujours préférable d'utiliser une classe statique ?

  2. Lorsqu'il y a un nombre considérable de ces définitions de classes statiques (disons 100 par exemple, avec un certain nombre de méthodes statiques chacune), cela affectera-t-il négativement les performances d'exécution ou la consommation de mémoire par rapport au même nombre de définitions de classes d'instance ?

  3. Lorsqu'une autre méthode de la même classe d'instance est appelée, la résolution d'instance se produit-elle toujours ? Par exemple, en utilisant le mot-clé [this] comme suit this.DoOperation2("abc") de l'intérieur DoOperation1 de la même instance.

188voto

Jon Hanna Points 40291

En théorie, une méthode statique devrait être légèrement plus performante qu'une méthode d'instance, toutes choses égales par ailleurs, en raison de l'ajout d'un élément caché supplémentaire. this paramètre.

En pratique, cela fait si peu de différence que cela sera caché dans le bruit des diverses décisions du compilateur. (Ainsi, deux personnes pourraient "prouver" que l'un est meilleur que l'autre avec des résultats divergents). D'autant plus que le this est normalement transmis dans un registre et se trouve souvent dans ce registre au départ.

Ce dernier point signifie qu'en théorie, nous devrions nous attendre à ce qu'une méthode statique qui prend un objet en paramètre et en fait quelque chose soit légèrement moins bonne que l'équivalent en instance sur ce même objet. Encore une fois, la différence est si mince que si vous essayez de la mesurer, vous finirez probablement par mesurer une autre décision du compilateur. (D'autant plus que la probabilité que cette référence soit dans un registre pendant tout ce temps est également assez élevée).

Les vraies différences de performances se résument à savoir si vous avez artificiellement placé des objets en mémoire pour faire quelque chose qui devrait naturellement être statique, ou si vous emmêlez des chaînes de passage d'objets de manière compliquée pour faire ce qui devrait naturellement être une instance.

D'où le numéro 1. Lorsque la conservation de l'état n'est pas une préoccupation, il est toujours préférable d'être statique, parce que c'est à ça que servent les statiques . Ce n'est pas un problème de performance, bien qu'il y ait une règle générale qui consiste à jouer gentiment avec les optimisations du compilateur - il est plus probable que quelqu'un ait fait l'effort d'optimiser les cas qui se présentent dans le cadre d'une utilisation normale que ceux qui se présentent dans le cadre d'une utilisation étrange.

Numéro 2. Ça ne fait aucune différence. Il y a un certain coût par classe pour chaque membre en termes de quantité de métadonnées, de quantité de code dans le fichier DLL ou EXE et de quantité de code ajouté. C'est la même chose qu'il s'agisse d'instance ou de statique.

Avec le point 3, this est comme this fait. Toutefois, notez bien :

  1. Le site this est passé dans un registre particulier. Lors de l'appel d'une méthode d'instance au sein de la même classe, le paramètre sera probablement déjà dans ce registre (à moins qu'il n'ait été caché et que le registre n'ait été utilisé pour une raison ou une autre). this à ce qu'il doit être réglé. Cela s'applique dans une certaine mesure, par exemple, aux deux premiers paramètres de la méthode qui sont les deux premiers paramètres d'un appel qu'elle effectue.

  2. Puisqu'il sera clair que this n'est pas nulle, cela peut être utilisé pour optimiser les appels dans certains cas.

  3. Puisqu'il sera clair que this n'est pas nulle, cela peut rendre les appels de méthode inlined plus efficaces, car le code produit pour simuler l'appel de méthode peut omettre certains contrôles de nullité dont il pourrait avoir besoin de toute façon.

  4. Cela dit, les contrôles nuls ne sont pas chers !

Il est intéressant de noter que les méthodes statiques génériques agissant sur un objet, plutôt que les méthodes d'instance, peuvent réduire certains des coûts discutés à l'article http://joeduffyblog.com/2011/10/23/on-generics-and-some-of-the-associated-overheads/ dans le cas où cette statique donnée n'est pas appelée pour un type donné. Comme il le dit lui-même : "En passant, il s'avère que les méthodes d'extension sont un excellent moyen de rendre les abstractions génériques plus payantes."

Cependant, notez que cela ne concerne que l'instanciation d'autres types utilisés par la méthode, qui n'existent pas autrement. En tant que tel, il ne s'applique pas vraiment à de nombreux cas (une autre méthode d'instance a utilisé ce type, un autre code quelque part ailleurs a utilisé ce type).

Résumé :

  1. Les coûts de performance de l'instance par rapport à la statique sont généralement négligeables.
  2. Les coûts qui en découlent sont généralement liés à l'utilisation abusive de l'électricité statique, par exemple, ou vice-versa. Si vous ne faites pas entrer en ligne de compte votre choix entre statique et instance, vous avez plus de chances d'obtenir le bon résultat.
  3. Il existe de rares cas où les méthodes génériques statiques d'un autre type entraînent la création de moins de types que les méthodes génériques d'instance. parfois ont un petit avantage à devenir rarement utilisées (et "rarement" fait référence aux types avec lesquels elles sont utilisées pendant la durée de vie de l'application, pas à la fréquence à laquelle elles sont appelées). Une fois que vous aurez compris de quoi il parle dans cet article, vous verrez que cela n'a rien à voir avec la plupart des décisions de type statique-vs-instance de toute façon. Edit : Et cela n'a ce coût qu'avec ngen, pas avec le code jitted.

Edit : Une note sur la façon dont les contrôles de nullité sont bon marché (ce que j'ai prétendu ci-dessus). La plupart des null-checks en .NET ne vérifient pas du tout l'existence de null, ils continuent plutôt ce qu'ils allaient faire en supposant que ça va fonctionner, et si une exception d'accès se produit, elle est transformée en un NullReferenceException . Ainsi, la plupart du temps, lorsque le code C# implique conceptuellement un contrôle de nullité parce qu'il accède à un membre d'instance, le coût s'il réussit est en fait nul. Une exception serait certains appels inlined, (parce qu'ils veulent se comporter comme s'ils appelaient un membre d'instance) et ils frappent juste un champ pour déclencher le même comportement, donc ils sont aussi très bon marché, et ils peuvent encore souvent être laissés de côté de toute façon (par exemple si la première étape de la méthode implique l'accès à un champ tel quel).

14voto

Tigran Points 41381

Lorsque la conservation de l'état n'est pas une préoccupation (aucun champ ou propriété n'est requis), est-il toujours préférable d'utiliser une classe statique ?

Je dirais que oui. Comme déclarer quelque chose static vous déclarez un intention de l'exécution sans état (ce n'est pas obligatoire, mais une intention de quelque chose que l'on pourrait attendre)

Lorsqu'il y a un nombre considérable de ces classes statiques (disons 100 par exemple, avec un certain nombre de méthodes statiques chacune), cela affectera-t-il les les performances d'exécution ou la consommation de mémoire par rapport par rapport au même nombre de classes d'instance ?

Je ne pense pas, sauf si vous êtes sûr que les classes statiques sont vraiment stetless, car sinon, il est facile de se tromper dans les allocations de mémoire et d'obtenir des fuites de mémoire.

Lorsque le mot-clé [this] est utilisé pour appeler une autre méthode dans le même fichier classe d'instance, la résolution d'instance se produit-elle toujours ?

Pas sûr, environ ce (il s'agit d'un détail purement lié à l'implémentation du CLR), mais pensez que oui.

-1voto

burning_LEGION Points 7262

Les méthodes statiques sont plus rapides mais moins OOP. Si vous utilisez des modèles de conception, les méthodes statiques sont probablement du mauvais code. La logique métier est mieux écrite en tant que méthode non statique. Les fonctions communes comme la lecture de fichiers, WebRequest, etc. sont mieux écrites en statique. Vos questions n'ont pas de réponse universelle.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X