c# - 为什么 .NET 中的已检查算法有时比未检查的算法快?

标签 c# .net integer-overflow

为什么当我在 C# Project Properties > Build > Advanced 下打开“check for arithmetic underflow/overflow”时,下面的代码运行速度(138 ms)比我关闭该选项(141 ms)时更快?

测试运行 #1:138 毫秒有检查算术,141 毫秒没有

using System;
using System.Diagnostics;

class Program
{
    static void Main(string[] args)
    {
        var s = new Stopwatch();
        s.Start();
        int a = 0;
        for (int i = 0; i < 100000000; i += 3) {
            if (i == 1000)
                i *= 2;
            if (i % 35 == 0)
                ++a;
        }
        s.Stop();
        Console.WriteLine(s.ElapsedMilliseconds);
        Console.WriteLine(a);
    }
}

另一方面,如果您注释掉 if (i == 1000) i *= 2;,则已检查的代码运行速度(120 毫秒)比未检查的代码(116 毫秒)慢).

测试运行 #2:120 毫秒,有检查算法,116 毫秒,没有

using System;
using System.Diagnostics;

class Program
{
    static void Main(string[] args)
    {
        var s = new Stopwatch();
        s.Start();
        int a = 0;
        for (int i = 0; i < 100000000; i += 3) {
            if (i % 35 == 0)
                ++a;
        }
        s.Stop();
        Console.WriteLine(s.ElapsedMilliseconds);
        Console.WriteLine(a);
    }
}

过程:在 Visual Studio 外部从 PowerShell 提示中手动运行 .exe,直到结果时间戳一致(± 1 毫秒);在设置之间多次切换以确保结果一致。

测试箱设置:

  • Windows 8.1 专业版 x64
  • VS2013 更新 2
  • 英特尔酷睿 i7-4500
  • 默认 C# 控制台项目模板
  • 发布配置

最佳答案

答案是您正在处理许多允许 JIT 做出永远不会溢出的安全假设的常量。如果您使用斐波那契基准之类的东西,区别就会变得很明显。

2770 毫秒与 4150 毫秒(AnyCPU,首选 32 位)

using System;
using System.Diagnostics;

class Program
{
    static void Main(string[] args)
    {
        var s = new Stopwatch();
        s.Start();
        int a = 0;
        for (int i = 0; i < 100000000; i++)
        {
            a = Fibonacci(45);
        }
        s.Stop();
        Console.WriteLine(s.ElapsedMilliseconds);
    }

    public static int Fibonacci(int n)
    {
        int a = 0;
        int b = 1;
        for (int i = 0; i < n; i++)
        {
            int temp = a;
            a = b;
            // if the JIT compiler is clever, only this one needs to be 'checked'
            b = temp + b; 
        }
        return a;
    }

}

关于c# - 为什么 .NET 中的已检查算法有时比未检查的算法快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23736786/

相关文章:

assembly - 寄存器AL和AX溢出到哪里?

c - 如果我们将最大的可表示整数加一,结果是否为负数?

c# - 你如何检查 DateTime 是否已初始化?

c# - AOP 脏跟踪

c# - 如何在 32 位或 64 位以及任何操作系统语言的 XP、Vista 和 7 中获取所有用户帐户名

使用Visual Studio 2008的.NET安装项目

c - 使用带有 uint64_t 类型的内置溢出函数

c# - ASP.NET MVC 全局变量

c# - 多对多映射未创建正确的表

c# - 函数来获取任何方法的名称?