En théorie, une méthode statique devrait fonctionner légèrement mieux qu'une méthode d'instance, toutes choses étant égales par ailleurs, en raison du this
paramètre caché supplémentaire .
En pratique, cela fait si peu de différence qu'il sera caché dans le bruit des diverses décisions du compilateur. (Par conséquent, deux personnes pourraient "prouver" l'une meilleure que l'autre avec des résultats en désaccord). Notamment, car le this
est normalement passé dans un registre et est souvent dans ce registre pour commencer.
Ce dernier point signifie qu'en théorie, nous devrions nous attendre à ce qu'une méthode statique qui prend un objet comme paramètre et fasse quelque chose avec lui soit légèrement moins bonne que l'équivalent en tant qu'instance sur ce même objet. Encore une fois, la différence est si légère que si vous essayez de la mesurer, vous finirez probablement par mesurer une autre décision du compilateur. (D'autant que la probabilité que cette référence soit dans un registre tout le temps est également assez élevée).
Les vraies différences de performances se résumeront à savoir si vous avez artificiellement 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 le maintien de l'état n'est pas un problème, il est toujours préférable d'être statique, car c'est à cela que sert la statique . Ce n'est pas un problème de performance, bien qu'il y ait une règle générale pour bien jouer avec les optimisations du compilateur - il est plus probable que quelqu'un se soit efforcé d'optimiser les cas d'utilisation normale que ceux qui présentent une utilisation étrange.
Numéro 2. Ne fait aucune différence. Il y a un certain montant de coût par classe pour chaque membre, en fonction de la quantité de métadonnées, de la quantité de code dans le fichier DLL ou EXE réel et de la quantité de code jit. C'est la même chose que ce soit une instance ou statique.
Avec l'élément 3, this
est commethis
ça. Notez cependant:
Le this
paramètre est passé dans un registre particulier. Lors de l'appel d'une méthode d'instance dans la même classe, elle sera probablement déjà dans ce registre (à moins qu'elle n'ait été cachée et que le registre soit utilisé pour une raison quelconque) et par conséquent, aucune action n'est requise pour définir lethis
sur ce qu'il doit être défini. . Cela s'applique dans une certaine mesure, par exemple aux deux premiers paramètres de la méthode étant les deux premiers paramètres d'un appel qu'elle effectue.
Comme il sera clair que ce this
n'est pas nul, cela peut être utilisé pour optimiser les appels dans certains cas.
Comme il sera clair que ce this
n'est pas nul, cela peut rendre les appels de méthode intégrés plus efficaces à nouveau, car le code produit pour simuler l'appel de méthode peut omettre certaines vérifications nulles dont il pourrait avoir besoin de toute façon.
Cela dit, les chèques nuls sont bon marché!
Il convient 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 à 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: «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, cela ne s'applique vraiment pas à de nombreux cas (une autre méthode d'instance a utilisé ce type, un autre code ailleurs utilisé ce type).
Résumé:
- La plupart du temps, les coûts de performance de l'instance par rapport au statique sont inférieurs à négligeables.
- Les coûts viendront généralement lorsque vous abusez de l'électricité statique, par exemple ou vice-versa. Si vous ne faites pas partie de votre décision entre statique et instance, vous aurez plus de chances d'obtenir le résultat correct.
- Il existe de rares cas où les méthodes génériques statiques dans un autre type entraînent la création de moins de types que les méthodes génériques d'instance, ce qui peut parfois avoir un petit avantage à devenir rarement utilisé (et "rarement" fait référence aux types avec lesquels il est utilisé dans le durée de vie de l'application, pas à quelle fréquence elle est appelée). Une fois que vous avez compris ce dont il parle dans cet article, vous verrez que de toute façon, cela n'est pas pertinent à 100% pour la plupart des décisions statiques contre instance. Edit: Et cela n'a surtout ce coût qu'avec ngen, pas avec du code jitted.
Edit: Une note sur à quel point les vérifications nulles sont bon marché (ce que j'ai réclamé ci-dessus). La plupart des vérifications nulles dans .NET ne vérifient pas du tout null, elles continuent plutôt ce qu'elles allaient faire avec l'hypothèse que cela fonctionnera, et si une exception d'accès se produit, elle est transformée en un fichier NullReferenceException
. En tant que tel, la plupart du temps lorsque conceptuellement le code C # implique une vérification nulle 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 intégrés, (car ils veulent se comporter comme s'ils appelaient un membre d'instance) et ils frappent simplement un champ pour déclencher le même comportement, donc ils sont également 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 impliquait d'accéder à un champ tel quel).