如何为接口callvirt .NET指导工作?何为、接口、工作、callvirt

2023-09-04 01:31:57 作者:ε槑*

解释虚拟分派给别人很简单:每个对象都有一个指向一个表作为其数据的一部分。上有N级虚拟方法。一个特定的方法,每次调用我的索引,当它到达并调用表中的第i个方法的对象。实现方法X(每级)将有code的方法X()在相同的第i个指标。

Explaining virtual dispatching to someone is easy: every object has a pointer to a table as part of its data. There are N virtual methods on the class. Every call to a particular method i indexes the object when it arrives and calls the ith method in the table. Every class that implements method X() will have the code for method X() in the same ith index.

但后来我们得到的接口。而且接口需要某种扭曲的,因为这两者实现相同的接口将在表的不同指数的虚函数两个非继承的类。

But then we get interfaces. And interfaces require some sort of contortion because two non-inheriting classes that both implement the same interface will have the virtual functions in different indexes of the table.

我在网上搜索了,而且也有很多讨论,我可以找到有关如何接口派遣的可以的实施。有两大类: 一)某种哈希表的查找对象上找到合适的调度表 b)在所述对象被转换为接口,创建一个新的指针指向相同的数据,但可以不同的V表

I have searched the Internet, and there are many discussions I can find about how interface dispatching can be implemented. There are two broad categories: a) some sort of hash table look up on the object to find the right dispatch table b) when the object is cast to the interface, a new pointer is created that points to the same data but to a different vtable.

但是,尽管大量的信息它是如何的可以的工作,我可以找到任何关于如何在.NET运行时引擎实际上实现它。

But despite lots of info about how it can work, I can find nothing about how the .NET runtime engine actually implements it.

有谁知道,描述了实际指针运算是发生在当对象类型是一个接口callvirt指令文件?

Does anyone know of a document that describes the actual pointer arithmetic that happens at a callvirt instruction when the object type is an interface?

推荐答案

接口的CLR调度是黑魔法。

Interface dispatching in the CLR is black magic.

正如你注意到,虚方法分派在概念上是很容易解释。

As you correctly note, virtual method dispatch is conceptually easy to explain. And in fact I do so in this series of articles, where I describe how you could implement virtual methods in a C#-like language that lacked them:

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

是我所描述的机制非常相似,实际使用的机制

The mechanisms I describe are quite similar to the mechanisms actually used.

接口调度更难形容,和CLR实现它的方式是不是在所有显而易见的。接口调度CLR机制都经过精心调整,以最常见的情况下提供高性能,并且这些机制的细节,因此会受到基础为CLR团队开发有关的使用现实世界的模式更多的知识来改变。

Interface dispatch is much harder to describe, and the way the CLR implements it is not at all apparent. The CLR mechanisms for interface dispatch have been carefully tuned to provide high performance for the most common situations, and the details of those mechanisms are therefore subject to change based as the CLR team develops more knowledge about real-world patterns of usage.

基本上,它在幕后工作的方式是每个调用点 - 那就是,在code每个点调用的接口方法 - 有一个小的缓存,说:我认为方法有关与此接口插槽是......在这里。的大多数时间,高速缓存是对的;你很少打电话相同的接口方法,一百万个不同的实现一百万次。它通常在一排相同的执行一遍又一遍,很多次了。

Basically the way it works behind the scenes is that each call site -- that is, each point in the code where an interface method is invoked -- there is a little cache that says "I think the method associated with this interface slot is... here". The vast majority of the time, that cache is right; you very seldom call the same interface method a million times with a million different implementations. It's usually the same implementation over and over again, many times in a row.

如果缓存原来是未命中然后它退到即保持哈希表,做一个稍慢查找

If the cache turns out to be a miss then it falls back to a hash table that is maintained, to do a slightly slower lookup.

如果是的原来是一个小姐,然后将对象元数据进行分析,以确定对应的接口插槽什么方法。

If that turns out to be a miss, then the object metadata is analyzed to determine what method corresponds to the interface slot.

该净效应是,在一个给定的调用点,如果你总是调用映射到特定的类方法的接口方法,它的非常的快。如果你总是调用几个类中的方法为给定的接口方法中的一种,表现为pretty的好。做的最糟糕的事情是在同一地点同一接口的方法来从未调用同一个类的方法两次;这需要最慢的路径每次。

The net effect is that at a given call site, if you always invoke an interface method that maps to a particular class method, it is very fast. If you always invoke one of a handful of class methods for a given interface method, performance is pretty good. The worst thing to do is to never invoke the same class method twice with the same interface method at the same site; that takes the slowest path every time.

如果你想知道的表慢查找如何保持在内存中,看到马修沃森的答案的链接。

If you want to know how the tables for the slow lookup are maintained in memory, see the link in Matthew Watson's answer.

 
精彩推荐
图片推荐