动态变量如何影响性能?

2024-03-03

我对性能有疑问dynamic在 C# 中。我读了dynamic让编译器再次运行,但它有什么作用呢?

是否必须使用以下命令重新编译整个方法dynamic变量用作参数还是仅那些具有动态行为/上下文的行?

我注意到使用dynamic变量可以使简单的 for 循环减慢 2 个数量级。

我玩过的代码:

internal class Sum2
{
    public int intSum;
}

internal class Sum
{
    public dynamic DynSum;
    public int intSum;
}

class Program
{
    private const int ITERATIONS = 1000000;

    static void Main(string[] args)
    {
        var stopwatch = new Stopwatch();
        dynamic param = new Object();
        DynamicSum(stopwatch);
        SumInt(stopwatch);
        SumInt(stopwatch, param);
        Sum(stopwatch);

        DynamicSum(stopwatch);
        SumInt(stopwatch);
        SumInt(stopwatch, param);
        Sum(stopwatch);

        Console.ReadKey();
    }

    private static void Sum(Stopwatch stopwatch)
    {
        var sum = 0;
        stopwatch.Reset();
        stopwatch.Start();
        for (int i = 0; i < ITERATIONS; i++)
        {
            sum += i;
        }
        stopwatch.Stop();

        Console.WriteLine(string.Format("Elapsed {0}", stopwatch.ElapsedMilliseconds));
    }

    private static void SumInt(Stopwatch stopwatch)
    {
        var sum = new Sum();
        stopwatch.Reset();
        stopwatch.Start();
        for (int i = 0; i < ITERATIONS; i++)
        {
            sum.intSum += i;
        }
        stopwatch.Stop();

        Console.WriteLine(string.Format("Class Sum int Elapsed {0}", stopwatch.ElapsedMilliseconds));
    }

    private static void SumInt(Stopwatch stopwatch, dynamic param)
    {
        var sum = new Sum2();
        stopwatch.Reset();
        stopwatch.Start();
        for (int i = 0; i < ITERATIONS; i++)
        {
            sum.intSum += i;
        }
        stopwatch.Stop();

        Console.WriteLine(string.Format("Class Sum int Elapsed {0} {1}", stopwatch.ElapsedMilliseconds, param.GetType()));
    }

    private static void DynamicSum(Stopwatch stopwatch)
    {
        var sum = new Sum();
        stopwatch.Reset();
        stopwatch.Start();
        for (int i = 0; i < ITERATIONS; i++)
        {
            sum.DynSum += i;
        }
        stopwatch.Stop();

        Console.WriteLine(String.Format("Dynamic Sum Elapsed {0}", stopwatch.ElapsedMilliseconds));
    }

我读过动态使编译器再次运行,但它做了什么。是否必须使用动态作为参数重新编译整个方法,或者更确切地说,那些具有动态行为/上下文的行(?)

事情是这样的。

对于每一个表达在动态类型的程序中,编译器会发出代码,生成表示操作的单个“动态调用站点对象”。因此,举例来说,如果您有:

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);

看看到目前为止效果如何?我们生成调用站点once,无论您调用 M 多少次。调用站点在您生成一次后将永远存在。调用站点是一个对象,表示“这里将动态调用 Foo”。

好的,既然您已经获得了调用站点,那么调用是如何工作的呢?

调用站点是动态语言运行时的一部分。 DLR 说“嗯,有人试图在此对象上动态调用 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;

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

合理?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

动态变量如何影响性能? 的相关文章

随机推荐

  • WPF 列表框项目不自动换行

    My ListBox其中有一个可能很长的描述字段 我不想使用水平滚动条 而是想自动换行 如果我设置它就有效MaxWidth但自从ListBox更改大小我不想对值进行硬编码 最好的方法是什么 编辑 描述位于TextBlock 简化的XAML
  • xml删除php中的子节点

    我试图通过 id 属性删除 druzenje 元素 我知道要做到这一点 我必须从该元素中删除所有子节点
  • 输出到精确的流浮点数

    我的浮点数精度有问题 int main void double b 106 829599 float a b std cerr lt lt std setprecision 6 lt lt a lt lt a lt lt b lt lt b
  • phonegap运行android报错

    每当我尝试使用构建项目时phonegap run 我收到以下错误 C Users MS AwaN my app gt phonegap run android phonegap detecting Android SDK environme
  • 学习 WCF RIA 服务的最佳资源

    您正在查看哪些书籍 视频 文章来了解如何使用新发布的 Silverlight WCF RIA 服务 1 起点是http www silverlight net getstarted riaservices http www silverli
  • nginx:将 ssl 连接转发到另一台服务器

    我有一个 nginx 主服务器 决定将请求路由到的传入服务器名称 对于两个辅助服务器 此主 nginx 服务器还保存 ssl 证书和密钥 第三台服务器拥有自己的证书和密钥 因为这些证书和密钥的更新过程很频繁 我现在的问题是如何配置主 ngi
  • 设置 svnperms 预提交挂钩

    我正在尝试将 svnperms 实现到存储库中 但在一些事情上遇到了困难 pre commit具有执行权限 rwxrwxr x 1 svnadm svn 3018 May 27 10 11 pre commit 这是我在预提交中对 svnp
  • BBP 算法所需的工作精度?

    我希望在低内存环境中计算 Pi 的第 n 位数字 由于我没有可用的小数 这Python 中的纯整数 BBP 算法 http en literateprograms org Pi with the BBP formula 28Python 2
  • vuetify-loader 1.6 与 laravel mix 不兼容,vue-loader 15 目前不支持 oneOf 的 vue 规则

    我正在尝试在 laravel 上安装 vue 我相信我明白了 但是当我运行 npm run watch 或 npm run dev 时 它会生成此错误 我尝试了几件事但无法解决 Error VueLoaderPlugin Error vue
  • Excel:使用外部链接可以提高性能吗?

    我想知道使用外部链接与打开电子表格和复制单元格 使用 VBA 相比是否有性能提升 我想 Excel 必须以同样的方式打开文件 但是当我使用以下代码进行测试时 外部链接速度更快 Dim t As Double Dim rng As Range
  • 使用 Xcode 6 从命令行进行 UIAutomation 测试调用

    在新的 Xcode 版本中 从命令行运行 UIAutomation 测试似乎经常会中断 根据过去的帖子判断 由于从未使用过命令行脚本 我发现了 2012 年的这篇文章 来自命令行的自动化仪器 https stackoverflow com
  • setup.py:如何查找用户指定的括号内的附加内容

    我有一个通过 PyPI 分发的包 其中包含大量数据 PyPI 有 100MB 的限制 我想分发比这更多的数据 数据相当不变 因此在每次代码发布时不断将大量数据推送到 PyPI 似乎也很浪费 相反 我更愿意分发最少的数据 并将大数据选项作为可
  • d3:不规则/分散数据的等高线或曲面图

    我可以采用一组三元组 X Y Z 并立即使用 Python 和 matplotlib 生成一个 平滑 等高线图单次通话 to 三角轮廓 https matplotlib org examples pylab examples tricont
  • 实时调试堆栈溢出

    我有一个托管代码 Windows 服务应用程序 由于托管 StackOverFlowException 该应用程序在生产中偶尔会崩溃 我知道这一点是因为我在崩溃模式下运行了 adplus 并使用 SoS 事后分析了崩溃转储 我什至附加了 W
  • Firebase:从 UID 获取 DisplayName [重复]

    这个问题在这里已经有答案了 我将用户的显示名称存储在 Firebase Auth 中 当同一用户登录时 从 Firebase Auth 获取很简单 但是 当另一个用户登录时 当我拥有帐户的唯一 UID 用户 ID 时 如何获取帐户的显示名称
  • 在 WebApplicationFactory 的配置源中关闭“ReloadOnChange”

    这既是一个问题 也是一个答案 我已经解决了我的问题 但似乎有点不对劲 我最初的问题是在 bitbucket 管道中运行我的 ASP NET Core 集成测试 原因是System IO IOException The configured
  • 不允许 HTTPS 页面运行来自 safari-extension:// URI 的不安全内容

    我在 Safari 9 1 11601 5 17 1 的 Safari 扩展中遇到了奇怪的行为 我尝试使用 safari extension 插入一个新的 Iframe 其 src 指向扩展包中的 html 文件 如果我单击控制台中显示的错
  • 无法在 Google 操作中使用隐式/授权流程来授权用户

    我正在尝试链接到该帐户 这是我的谷歌云功能 var AuthHandler function this googleSignIn googleSignIn this googleSignInCallback googleSignInCall
  • C# - 如何使两个表单相互引用

    我正在用 MS Visual C 编写一个 WindowsForms 应用程序 我需要两个表单才能相互引用 在测试时 我在 Form1 上创建了两个按钮 一个按钮显示 Form2 另一个按钮隐藏它 代码如下 我想对 Form2 做同样的事情
  • 动态变量如何影响性能?

    我对性能有疑问dynamic在 C 中 我读了dynamic让编译器再次运行 但它有什么作用呢 是否必须使用以下命令重新编译整个方法dynamic变量用作参数还是仅那些具有动态行为 上下文的行 我注意到使用dynamic变量可以使简单的 f