Try-catch 可以加速我的代码吗?

2023-12-12

我编写了一些代码来测试 try-catch 的影响,但看到了一些令人惊讶的结果。

static void Main(string[] args)
{
    Thread.CurrentThread.Priority = ThreadPriority.Highest;
    Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime;

    long start = 0, stop = 0, elapsed = 0;
    double avg = 0.0;

    long temp = Fibo(1);

    for (int i = 1; i < 100000000; i++)
    {
        start = Stopwatch.GetTimestamp();
        temp = Fibo(100);
        stop = Stopwatch.GetTimestamp();

        elapsed = stop - start;
        avg = avg + ((double)elapsed - avg) / i;
    }

    Console.WriteLine("Elapsed: " + avg);
    Console.ReadKey();
}

static long Fibo(int n)
{
    long n1 = 0, n2 = 1, fibo = 0;
    n++;

    for (int i = 1; i < n; i++)
    {
        n1 = n2;
        n2 = fibo;
        fibo = n1 + n2;
    }

    return fibo;
}

在我的计算机上,这始终打印出 0.96 左右的值。

当我用 try-catch 块将 for 循环包装在 Fibo() 内时,如下所示:

static long Fibo(int n)
{
    long n1 = 0, n2 = 1, fibo = 0;
    n++;

    try
    {
        for (int i = 1; i < n; i++)
        {
            n1 = n2;
            n2 = fibo;
            fibo = n1 + n2;
        }
    }
    catch {}

    return fibo;
}

现在它始终打印出 0.69...——它实际上运行得更快!但为什么?

注意:我使用 Release 配置编译它并直接运行 EXE 文件(在 Visual Studio 之外)。

EDIT: 乔恩·斯基特出色的分析表明在这种特定情况下,try-catch 在某种程度上导致 x86 CLR 以更有利的方式使用 CPU 寄存器(我认为我们还没有理解为什么)。我证实了 Jon 的发现,x64 CLR 没有这种差异,而且它比 x86 CLR 更快。我也测试过使用intFibo 方法中的类型而不是long类型,然后 x86 CLR 与 x64 CLR 一样快。


UPDATE:看起来这个问题已经被 Roslyn 解决了。相同的机器,相同的 CLR 版本 - 使用 VS 2013 编译时问题仍然如上,但使用 VS 2015 编译时问题消失。


中的一个Roslyn专门研究堆栈使用优化的工程师对此进行了研究,并向我报告说,C# 编译器生成局部变量存储的方式与 C# 编译器生成局部变量存储的方式之间的交互似乎存在问题。JIT编译器在相应的 x86 代码中注册调度。结果是在本地加载和存储上生成次优代码。

由于某些我们所有人都不清楚的原因,当 JITter 知道该块位于 try 保护区域中时,就会避免有问题的代码生成路径。

这很奇怪。我们将与 JITter 团队跟进,看看是否可以输入错误,以便他们可以修复此问题。

此外,我们正在努力改进 Roslyn 对 C# 和 VB 编译器的算法,以确定何时可以将本地变量设置为“临时”——也就是说,仅将其压入和弹出堆栈,而不是在堆栈上分配特定位置激活的持续时间。我们相信,如果我们能够更好地提示 JITter 何时可以更早地使本地变量“死亡”,那么 JITter 将能够更好地完成寄存器分配等工作。

感谢您提请我们注意这一点,并对奇怪的行为表示歉意。

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

Try-catch 可以加速我的代码吗? 的相关文章

随机推荐

  • Java 中的调度异常

    我正在开发一个任务 需要从给定的 URL 下载文件 其中一个要求是它可以处理网络故障和异常 在我的实现中 我有一个 DonwloadManager 为每个 URL 分配一个线程 以免阻塞 问题是我不确定如何通过代码模拟失败和异常 我尝试使用
  • 如何为 Cydia 和越狱的 iPhone 开发应用程序

    我开始为 iPhone 开发应用程序 我想开发一个特定的应用程序 但苹果肯定会拒绝它 所以我想为 Cydia 开发它 因为我认为它很有用 我试图弄清楚如何使用 Theos 和 XCode 来创建我的应用程序 但我什么都不懂 如果你们中的一些
  • Rails 基于对象的权限/授权引擎?

    我想在我的应用程序中添加 共享文档 功能 就像在谷歌文档服务中一样 据我所知 用户可以 可以列出 查看 创建 编辑 删除自己的文档 与所有人共享自己的文档 它是公共文档 将自己的文档共享给具有只读访问权限的其他用户 将自己的文档共享给具有读
  • 如何从 JSON 对象中删除包装器?

    我有一个带有包装器的 JSON 对象 其中包含有关它来自的服务的信息 在解析我真正关心的对象之前 我想去掉包装器 然后只解析该对象 我如何转换这个 JSON 对象 object id object 1 description Black o
  • 有没有API可以同时获取后置和前置摄像头视图? [复制]

    这个问题在这里已经有答案了 我需要在一个显示器上显示后置摄像头和前置摄像头 是否可以同时显示两者 有没有可以同时获取两个视图的API 与单相机相同 只是双相机 两个 SurfaceHolder 和两个 Camera 实例 http deve
  • TLS 扩展“服务器名称指示”(SNI):值在服务器端不可用

    基于 JSSE 示例 我尝试在服务器端获取 TLS 参数 服务器名称指示 SNI 的值 但没有成功 我确信该值是由客户端发送的 因为我使用了显示该值的网络嗅探器 Wireshark 但是当我使用以下代码片段时 服务器名称参数列表为空 同时显
  • 在令牌后触发的 jQuery 自动完成插件

    我正在构建一个应用程序 并且希望在文本区域内进行自动完成 就像 Twitter Facebook 使用 name 所做的那样 但是 我希望在输入 TID x 时触发它 其中 x 是任意长度的整数 看来 Twitter Facebook 在您
  • Google 电子表格 CTRL+Shift+E

    我有两张纸的电子表格 current sheet and archive sheet 我还有一个脚本 我创建的 可以从中删除数据current sheet并将其附加到archive sheet每月一次 The sheets have an
  • 使用FutureBuilder时如何只获取一次数据?

    我有一个获取请求 我将其作为未来传递给 FutureBuilder FutureBuilder future gettask builder context snapshot if snapshot hasData Stopwatch st
  • 如何解决 Mvc 中没有为此对象定义无参数构造函数错误?

    我正在创建一个演示应用程序来学习如何使用存储库模式来执行插入操作 我正在使用 Nop Commerce http www nopcommerce com 存储库模式的代码 Error 没有为此对象定义无参数构造函数 我看过这个链接 MVC
  • 哪个应该首先运行 git submodule update 或 git submodule init ?

    我在这里看到 https github com UCSD PL proverbot9001 issues 73 run git submodule update and the makes sure init is only ran if
  • 从 url 中删除“index.html”并使用单个 301 重定向添加“www”

    为了去除index html or index htm从网址我在我的中使用以下内容 htaccess RewriteCond REQUEST URI index html NC RewriteRule index html 1 NC R 3
  • Golang 中的 AES 加密和 Java 中的解密

    我用 Golang 编写了以下 AES 加密函数 func encrypt key byte text string string plaintext byte text block err aes NewCipher key if err
  • Flex:是否可以停止远程调用?

    我搜索了很长时间 但仍然没有找到答案 在常见情况下 我们保留远程方法调用的令牌 例如 Flex gt Java 但是 如果客户端知道不再需要当前调用 如何停止服务器处理 使用asyncToken 是否可以停止远程调用 感谢您的回答 据我了解
  • 如何使用 Devise 将 Rails 应用程序转变为 SSO/CAS 服务器?

    我从一个上一个问题我一直在问错误的问题 我想将我的应用程序变成 CAS 服务器 以便应用程序的管理员可以使用相同的身份验证机制来登录我们为组织开发的其他应用程序 你以前做过这个吗 是否有一个插件可以增加 Devise 充当 CAS 服务器的
  • relativeLayout.RIGHT_OF 不起作用

    我正在尝试在现有的相对布局中以编程方式创建一个文本视图和一个按钮 这个想法是将textview放在parentView relativeLayout 的左上角 然后将按钮添加到textView的右侧 但在应用程序中 它们看起来像是在同一个地
  • 对象字段序列

    我有一个用 JavaScript 代码编写的 JavaScript 对象 如下所示 var rtnStr 000 area000 020 area020 030 area030 040 area040 047 area047 049 are
  • Google Apps 脚本 - 获取 doPost 的 IP 并在电子表格中进行跟踪

    有没有一种简单的方法来捕获d的IPoPost e 请求并将其与 POST 的传入值一起存储以跟踪请求的来源 它似乎无法通过e parameter 我找不到其他属性或方法的完整列表e 目前无法获取传入请求的 IP 地址或用户代理doGet o
  • 如何使用 Selenium 和 Xpath 通过忽略大小写的文本查找元素

    我使用的是java版本 1 8 0 191 和selenium 3 141 59 我试图找出页面是否包含 error 或 erreur 一词 另外 我希望它不区分大小写 查找文本很容易 List
  • Try-catch 可以加速我的代码吗?

    我编写了一些代码来测试 try catch 的影响 但看到了一些令人惊讶的结果 static void Main string args Thread CurrentThread Priority ThreadPriority Highes