39 votes

Comment le callvirt .NET travail d'instruction pour les interfaces?

Expliquant virtuel envoi à quelqu'un, c'est simple: chaque objet est un pointeur vers une table dans le cadre de ses données. Il y a N méthodes virtuelles de la classe. Chaque appel à une méthode particulière, je l'index de l'objet lorsqu'il arrive et appelle la ith méthode dans le tableau. Toute classe qui implémente la méthode X() le code de la méthode X() dans le même ith index.

Mais alors nous obtenons des interfaces. Et interfaces nécessitent une sorte de contorsion parce que deux non-héritant des classes qui implémentent la même interface les fonctions virtuelles dans les différents index de la table.

J'ai cherché sur Internet, et il y a beaucoup de discussions que je peux trouver sur la façon de l'interface expédition peut être mis en œuvre. Il existe deux grandes catégories: a) une sorte de table de hachage de regarder sur l'objet à trouver la bonne expédition table b) lorsque l'objet est jeté à l'interface, un nouveau pointeur est créé points pour les mêmes données, mais à un autre vtable.

Mais en dépit de beaucoup d'informations sur la façon dont il peut travailler, je ne trouve rien sur la manière dont la .NET moteur d'exécution fait l'implémente.

Quelqu'un sait-il d'un document qui décrit l'arithmétique des pointeurs qui se passe à un callvirt l'instruction lorsque le type d'objet est une interface?

37voto

Eric Lippert Points 300275

Interface expédition dans le CLR est de la magie noire.

Comme vous l'avez remarque, la répartition de méthode virtuelle est conceptuellement simple à expliquer. Et en fait je le fais dans cette série d'articles, où je décris la façon dont vous pourriez mettre en œuvre des méthodes virtuelles en C#comme langage qui en ont pas:

http://blogs.msdn.com/b/ericlippert/archive/2011/03/17/implementing-the-virtual-method-pattern-in-c-part-one.aspx

Les mécanismes que je décris sont tout à fait semblables aux mécanismes utilisés.

L'Interface de l'expédition est beaucoup plus difficile à décrire, et la façon dont le CLR il n'est pas du tout évident. Le CLR mécanismes pour l'interface de répartition ont été soigneusement réglée pour offrir de hautes performances pour les situations les plus courantes, et les détails de ces mécanismes sont donc sujettes à changement en fonction que le CLR équipe développe de plus amples connaissances sur le monde réel des tendances d'utilisation.

Fondamentalement, la façon dont il fonctionne en arrière-plan, c'est que chaque site d'appel-qui est, chaque point dans le code où une méthode d'interface est appelée -- il y a un petit cache qui dit "je pense que la méthode associée à cette interface slot est... ici". La grande majorité du temps, ce cache est juste; vous avez très rarement appel à la même méthode de l'interface d'un million de fois avec un million de différentes implémentations. C'est généralement la même mise en œuvre maintes et maintes fois, beaucoup de fois dans une rangée.

Si le cache s'avère être un échec, alors il revient à une table de hachage qui est entretenu, à faire un peu plus lent de recherche.

Si qui s'avère être un échec, puis les métadonnées de l'objet est analysé afin de déterminer quelle méthode correspond à l'interface de la fente.

L'effet net est un site d'appel, si vous avez toujours appeler une méthode de l'interface qui correspond à une classe particulière de la méthode, il est très rapide. Si vous avez toujours invoquer l'un d'une poignée de méthodes de la classe pour une méthode de l'interface, la performance est assez bonne. La pire chose à faire est de ne jamais invoquer la même méthode de classe deux fois avec la même méthode d'interface sur le même site; qui prend le plus lent chemin à chaque fois.

Si vous voulez savoir comment les tables de la lenteur de recherche sont conservés dans la mémoire, voir le lien dans Matthieu Watson réponse.

14voto

Matthew Watson Points 30804

Parce que le compilateur a toujours effective de l'objet sur lequel l'appel à la méthode (à l'exécution), il sait toujours au moment de l'exécution le type de béton qu'il a à gérer.

Le code qui appelle une méthode virtuelle tout d'abord, on détermine le type de l'objet en cours d'utilisation. Ensuite, il consulte le type de la méthode de la table à la recherche de la méthode appelée. Le code appelle simplement la méthode, passage de la référence de l'objet comme "ceci", avec tous les autres paramètres.

Je crois que l'essentiel bits qui vous intéresse est de savoir comment le code de la recherche l'adresse de la méthode dans le type de la méthode de la table.

Plus de détails sur la méthode de la table sont donnés ici: http://msdn.microsoft.com/en-us/magazine/cc163791.aspx

Il est encore un peu la main ondulé sur exactement comment la recherche est effectuée, mais il donne tout un tas d'autres détails.

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