【问题标题】:if statement performance in c# [closed]c#中的if语句性能[关闭]
【发布时间】:2013-12-08 03:18:06
【问题描述】:

我只是想确定每个“if”语句对我的 C# 应用程序性能的影响,当它在具有大量迭代的循环中使用时。我还没有找到关于这个的主题,所以我创建了这个。

对于测试,我做了 2 个循环:一个没有“if”,一个只有一个“if”语句。代码如下。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;

namespace IfPerformance
{
    class Program
    {
        static void Main(string[] args)
        {
            int N = 500000000;
            Stopwatch sw = new Stopwatch();

            double a = 0, b = 0;
            bool f;

            sw.Restart();
            for (int i = 0; i < N; i++)
            {
                a += 1.1;
                f = a < N;
            }
            sw.Stop();
            Console.WriteLine("Without if: " + sw.ElapsedMilliseconds + " ms");

            a = 0;
            sw.Restart();
            for (int i = 0; i < N; i++)
            {
                if (a < N)
                    a += 1.1;
                else
                    b += 1.1;
            }
            sw.Stop();
            Console.WriteLine("With if:    " + sw.ElapsedMilliseconds + " ms");
            Console.ReadKey();
        }
    }
}

我使用“优化代码”构建选项和“不调试就开始”运行了测试。结果如下: 如果没有:154 毫秒 如果:742 毫秒

这意味着单个“if”语句会使性能降低近 5 倍。我认为这会有所帮助。

另外,我注意到在一个大循环中存在几个额外的“if”可能会使我的最终应用程序减慢 25%,我认为这很重要。

具体来说,我正在对一组数据运行 Monte-Carlo 优化,这需要对整个数据集进行多次循环。循环包含取决于用户设置的分支。从这一点开始出现“如果”。

我在性能方面向专业人士提出的问题是:

  1. 循环中额外的“if”对运行多次迭代的时间有何影响?
  2. 如何避免减速?

如果我走错了方向,请发表您的意见。

【问题讨论】:

  • 这些代码示例是两个不同的代码,一个是布尔赋值,另一个是条件语句,因此这不是评估性能的合适方法。
  • 不要沉迷于这样的微优化。无论如何,编译器可能会优化你的很多代码。您无法在调试模式下可靠地进行性能测试。在您了解用户期望后,使用外部工具对整个程序进行最佳性能测试
  • 我添加了布尔赋值来补偿第二个循环中比较操作的时间,并确定纯“if”语句的速度
  • 所以您已经确定执行 i​​f 语句需要 1.484 纳秒...
  • 在一个好的编译器中,你的代码会立即终止,因为它实际上并没有做任何事情。这使您的基准测试变得非常糟糕,if 语句的成本也很难衡量,因为它在很大程度上取决于分支预测和推测执行对于此特定代码和数据模式的工作情况。但总的来说if 相当昂贵,我尽量避免在高性能代码中使用它。

标签: c# .net performance


【解决方案1】:

没关系... 您正在测试 5 亿次迭代……它只需要不到一秒钟的时间……在最坏的情况下……

正如 cmets 所说,一开始您将遇到麻烦,因为您不会在调试中运行以测试性能,即使如此,您也会有大量其他事情需要考虑(这是一个关于性能测试的大世界,它并不像通常看起来那么简单)。

现在,请注意您在这两个地方做了两件不同的事情。如果您想查看 if 的性能,您应该让它们基本相同。我确定分支会将 IL 代码更改为以 ...

最后但并非最不重要的一点,正如我再次说过的那样......这并不重要......除非你真的需要运行 5 亿次,并且在很多地方都有这个,以至于你的程序开始变慢,因为那个。

如果你可以在 if 语句上节省一些微秒,那么就去追求可读性而不是痴迷

请随意阅读Eric Lippert 撰写的这些文章(“只有”250K 代表,并且 i̶s̶ 是 C# 编译器团队的主要开发人员 :),他们将引导您走向正确的方向:

(说到这个,我猜垃圾收集(第 4 条)可能是需要考虑的事情......)

那就看:this elaborate answer about the topic

最后但并非最不重要的是,看看Writing Faster Managed Code: Know What Things Cost。这是来自 Microsoft CLR 性能团队的 Jan Gray。老实说,我还没有读过这篇 :)。不过我会的,以后……

它继续... :)

【讨论】:

  • @Noctis 1) 我确实需要数百万次迭代(我对一组数据运行一些优化过程)2) 正如我所提到的,我在发布模式下运行 3) 在我的最终应用程序中循环中存在几个“if”会导致 25% 的整体减速,在我看来这是相当大的。非常感谢您提供的良好链接。
  • @Kudral 然后发布一个关于(简化版)您的真实应用程序的问题。您的基准测试并不代表任何实际工作量。至少对于整数运算,通常可以通过使用一些位移和掩码来消除ifs。我经常在我的加密代码中这样做。
  • 我也进行了很多基准测试,而且我的偏好在某些方面与 Eric 不同。例如,我经常使用挂钟 (UtcNow),而忽略了第一次运行是不同的。这些只对短期运行的基准很重要,而不是运行一分钟的基准。 Eric 还忘记提及我遇到的一些最重要的错误,例如忘记禁用 Turbo Boost 或让后台程序窃取一点 CPU 时间。
  • 感谢您的支持;我注意到我 C# 编译器开发团队的成员;我现在不在。
  • @EricLippert 嘿,Eric,链接好像坏了,tech.pro 的链接根本不工作(甚至进入一个看起来很狡猾的谷歌搜索页面)
【解决方案2】:

这些代码示例是两个不同的代码,一个是布尔赋值,另一个是条件语句,因此这不是评估性能的合适方法

【讨论】:

    【解决方案3】:

    这些基准基本上没有告诉您任何信息。 除了额外的 if 之外,还有更多的事情在起作用。 您还必须考虑分支预测和缓存。 这样的微优化只会阻碍你编写好的代码。 您将花费更多时间来优化无用的东西,而不是花时间在您的软件中实现好的功能......

    这样想,如果您的代码中有一个设计错误,任何优化都无济于事。 例如使用不合适的数据结构(例如“快速”查找的列表而不是字典)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-29
      • 2016-07-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-27
      • 1970-01-01
      • 2020-01-14
      相关资源
      最近更新 更多