具有动态变量如何影响性能?

具有动态变量如何影响性能?,第1张

具有动态变量如何影响性能?

我读过动态使编译器再次运行,但它能做什么。它是否必须使用动态参数作为参数重新编译整个方法,还是使用动态行为/上下文(?)

这是交易。

对于程序中动态类型的每个 表达式 ,编译器都会发出代码,该代码生成代表 *** 作的单个“动态调用站点对象”。因此,例如,如果您有:

class C{    void M()    {        dynamic d1 = whatever;        dynamic d2 = d1.Foo();

那么编译器将生成道德上像这样的代码。(实际代码要复杂得多;出于演示目的,已对其进行了简化。)

class C{    static DynamicCallSite FooCallSite;    void M()    {        object d1 = whatever;        object d2;        if (FooCallSite == null) FooCallSite = new DynamicCallSite();        d2 = FooCallSite.DoInvocation("Foo", d1);

到目前为止,如何运作?无论您呼叫M多少次,我们都会生成 一次 呼叫站点。 一旦 生成 一次
,呼叫站点将永久存在。呼叫站点是一个对象,表示“这里将是对Foo的动态呼叫”。

好,现在您已经有了呼叫站点,调用如何工作?

呼叫站点是动态语言运行时的一部分。DLR说:“嗯,有人试图对此here对象进行方法foo的动态调用。对此我是否一无所知?不,那么我最好找出来。”

然后DLR询问d1中的对象以查看它是否特殊。可能是旧版COM对象,Iron Python对象,Iron Ruby对象或IE
DOM对象。如果不是这些,则它必须是普通的C#对象。

这是编译器再次启动的点。不需要词法分析器或解析器,因此DLR启动了C#编译器的特殊版本,该版本仅具有元数据分析器,表达式的语义分析器以及发出表达式树而不是IL的发射器。

元数据分析器使用反射来确定d1中对象的类型,然后将其传递给语义分析器以询问在方法Foo上调用该对象时会发生什么。重载解析器会找出这个问题,然后构建一个表达式树-
就像您在表达式树lambda中调用Foo一样,代表该调用。

然后,C#编译器将该表达式树与缓存策略一起传递回DLR。该策略通常是“第二次看到这种类型的对象时,您可以重新使用此表达式树,而无需再次给我回电”。然后DLR在表达式树上调用Compile,后者会调用表达式树到IL的编译器,并在委托中吐出一块动态生成的IL。

然后,DLR将该委托缓存在与呼叫站点对象关联的缓存中。

然后,它调用委托,然后进行Foo调用。

第二次您致电M,我们已经有一个呼叫站点。DLR再次询问该对象,如果该对象与上次的类型相同,则它将委托从缓存中取出并调用它。如果对象的类型不同,则高速缓存将丢失,并且整个过程将重新开始;否则,整个过程将重新开始。我们对调用进行语义分析,并将结果存储在缓存中。

对于涉及动态的 每个表达式都会 发生这种情况。因此,例如,如果您有:

int x = d1.Foo() + d2;

那么就有 三个
动态呼叫站点。一种用于对Foo的动态调用,一种用于动态加法,一种用于从dynamic到int的动态转换。每个人都有自己的运行时分析和分析结果缓存。

合理?



欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5014858.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-11-14
下一篇2022-11-14

发表评论

登录后才能评论

评论列表(0条)

    保存