【问题标题】:Does C# Compiler calculate math on constants?C# 编译器是否计算常量的数学?
【发布时间】:2013-01-23 00:54:19
【问题描述】:

给定以下代码:

const int constA = 10;
const int constB = 10;

function GetX(int input) {
    int x = constA * constB * input;
    ...
    return x;
}

.Net 编译器是否会“替换”表达式并放入 1000,这样计算就不会一遍又一遍地重复?

在什么情况下代码运行最快:

  1. int x = constA * constB * input;
    
  2. int x = 10 * 10 * input;
    
  3. int x = 100 * input;
    

我猜选项 3 会比 2 更快,但有时不是最易读的选项。编译器会识别出这样的模式并进行相应的优化吗?

【问题讨论】:

  • 你的意思是把 '100' 而不是 '1000' :) 你能不能用 ILSpy 来检查这个?
  • 在一天结束时,您仍然需要乘以变量input,这将是瓶颈。那何必呢?
  • 给定的问题被简化以快速显示问题。我当然可以给你类等的完整继承……但我选择不这样做。
  • 题外话,如果你多次调用GetX方法,你可以通过去掉x变量并使用return constA * constB * input;而不是return x;来提高它的性能。跨度>
  • @AlexFilipovici - 这是一个相当大胆的断言,因为我们不知道 ... 做了什么(包括对 x 的任何访问),而且我们不知道 JIT 会做什么如果这些 GetX 函数的唯一部分,则必须这样做。断言消除局部变量会(没有任何限制)提高性能是没有根据的。

标签: c# performance constants compiler-optimization


【解决方案1】:

C# Constant Expressions:

只要表达式属于上面列出的类型之一并且只包含上面列出的结构,就会在编译时计算表达式。即使表达式是包含非常量结构的较大表达式的子表达式也是如此。

(如果您愿意,还可以阅读更多内容)所指的“上面”是一个项目符号列表,包括:

  • 对类和结构类型的 const 成员的引用。

和,

  • 预定义的 +、–、*、/、%、>、&、|、^、&&、||、==、!=、、= 二元运算符, 前提是每个操作数都属于上面列出的类型。

所以,直接回答你的问题,是的,编译器会在编译时执行计算。

【讨论】:

    【解决方案2】:

    我在 LINQPad 中试过这个:

    const int constA = 2;
    const int constB = 50;
    
    void Main()
    {
    
        Console.WriteLine(GetX(12));
    }
    
    int GetX(int input) 
    {
        int x = constA * constB * input;
    
        return x;
    }
    

    IL 是:

    十六进制的 64 值(十进制的 100)是常数相乘的结果。 mul 运算是乘以input

    所以听起来像应用于常量的操作是由编译器优化的。

    【讨论】:

    • 糟糕,错字。固定的。谢谢!
    猜你喜欢
    • 2011-01-04
    • 2011-09-04
    • 2022-06-23
    • 1970-01-01
    • 2013-04-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多