编写if语句是否会不同地影响程序的速度和效率?

时间:2018-08-19 12:56:31

标签: c# performance

我很好奇是否以不同的方式编写if语句会影响程序的速度和效率。因此,例如编写这样的代码:

bool isActive = true;

bool isResponding = false;

if (isActive && isResponding)
{
     //do this
}

是否比:

if (isActive)
{
    if (isResponding)
    {
       // do this
    }
}

或者反之亦然,或者根本没有区别吗?我问这个if语句的原因是因为AND &&及其编译后创建的asm函数的数量。或如何:

if (isActive || isResponding)
{
   //do this
}

这比以下方法更理想:

if (isActive)
{
    //do this #1
}
else if (isResponding)
{
    //do this #1
}
//do this #2

就像使用AND &&一样,我很好奇,因为OR ||

4 个答案:

答案 0 :(得分:3)

不,它不会影响性能,因为&&||被称为“短路运算符”,也就是说,如果其中没有任何意义,则不会触发它们链接的语句。这样做。

例如

if( true && myBoolFunc() )-myBoolFunc将触发,因为在检查true之后,我们仍然不知道整个语句是否为真。

if( false && myBoolFunc() )-myBoolFunc将不会触发,因为在检查false后,我们已经知道整个语句是错误的。

if( true || myBoolFunc() )-myBoolFunc将不会触发,因为在检查true之后,我们已经知道整个语句都是正确的。

if( false || myBoolFunc() )-myBoolFunc将被触发,因为在检查false之后仍然不知道整个语句是否为假。

如果您想了解有关其工作原理的更多详细信息,只需阅读此Wikipedia article

答案 1 :(得分:1)

我只是出于好奇而测量,结果并没有说明两者之间存在差异。

测试代码:

private static void testIfs()
{
    int count = 100000;

    {
        Stopwatch w = Stopwatch.StartNew();

        int test = 0;
        bool isActive = true;
        bool isResponding = false;
        for (int j = 0; j < count; j++)
            for (int i = 0; i < count; i++)
                if (isActive && isResponding)
                    test++;

        test = 0;
        isActive = false;
        isResponding = true;
        for (int j = 0; j < count; j++)
            for (int i = 0; i < count; i++)
                if (isActive && isResponding)
                    test++;

        w.Stop();
        Console.WriteLine("using &&: " + w.ElapsedTicks);
    }

    {
        Stopwatch w = Stopwatch.StartNew();

        int test = 0;
        bool isActive = true;
        bool isResponding = false;
        for (int j = 0; j < count; j++)
            for (int i = 0; i < count; i++)
                if (isActive)
                    if (isResponding)
                        test++;

        test = 0;
        isActive = false;
        isResponding = true;
        for (int j = 0; j < count; j++)
            for (int i = 0; i < count; i++)
                if (isActive)
                    if (isResponding)
                        test++;

        w.Stop();
        Console.WriteLine("using 2 ifs: " + w.ElapsedTicks);
    }

    {
        Stopwatch w = Stopwatch.StartNew();

        int test = 0;
        bool isActive = true;
        bool isResponding = false;
        for (int j = 0; j < count; j++)
            for (int i = 0; i < count; i++)
                if (isActive || isResponding)
                    test++;

        test = 0;
        isActive = false;
        isResponding = true;
        for (int j = 0; j < count; j++)
            for (int i = 0; i < count; i++)
                if (isActive || isResponding)
                    test++;

        w.Stop();
        Console.WriteLine("using ||: " + w.ElapsedTicks);
    }
    {
        Stopwatch w = Stopwatch.StartNew();

        int test = 0;
        bool isActive = true;
        bool isResponding = false;
        for (int j = 0; j < count; j++)
            for (int i = 0; i < count; i++)
                if (isActive)
                    test++;
                else if (isResponding)
                    test++;

        test = 0;
        isActive = false;
        isResponding = true;
        for (int j = 0; j < count; j++)
            for (int i = 0; i < count; i++)
                if (isActive)
                    test++;
                else if (isResponding)
                    test++;

        w.Stop();
        Console.WriteLine("using else if: " + w.ElapsedTicks);
    }
}

尝试一些(启用优化代码的发布版本):

using &&: 21449771
using 2 ifs: 20845600
using ||: 21025834
using else if: 21018318

using &&: 21041437
using 2 ifs: 21899080
using ||: 20442059
using else if: 21345493

using &&: 20629055
using 2 ifs: 20135598
using ||: 20407510
using else if: 20264467

using &&: 20152862
using 2 ifs: 19676131
using ||: 19910502
using else if: 19918131

答案 2 :(得分:0)

对于您所建议的方案没有任何影响。编译器会自动处理它并执行大量优化。

但是,即使编译器也有局限性。它不知道哪些值通常会分配给变量。作为开发人员,您会知道的。

在您的示例中:

main

很明显,如果bool isActive = <RETVAL_OF_SOME_FUNCTION>; bool isResponding = <RETVAL_OF_SOME_FUNCTION>; if (isActive && isResponding) { //do this } 为假,我们就不必为isResponding而烦恼。因此,isActive应该在AND条件的语句序列中首先出现。这样可以确保在运行时,isActive为假时不会浪费检查isResponding的处理能力。(如果{{1 }}是错误的)

尽管这是一个很小的优化,但编译器不会完成。编译器将不知道变量代表什么。它只会寻找预编程的优化并实现它。

在这种“与”或“或”的级联中,控制条件应始终优先。

可能存在两种性能下降的情况:

  • 数据获取过多
    太多的提取操作会大大降低您的工作速度。从RAM提取数据通常需要200-300个处理器周期。从L1缓存加载仅需要1-3个周期。加载过多的数据可能会/也将导致页面错误,从而导致从HDD存储设备加载,这甚至更慢。处理器将在加载过程中空闲等待

  • 结构不良的代码
    不要使用某些元素为空的结构。一个Excel单元格就是一个例子。每个单元格都有很多字段,因此复制一个单元格将复制很多信息。我猜他们可能已经实现了优化的逻辑(不知道),但避免使用大型数据结构。这将增加线程处理以及作为函数参数传递时的开销。

    它们的效果看似微不足道,但从长远来看,如果您要在系统中重复运行它,它们的效果会加在一起。

    如果代码每天运行少于1000次(取决于代码执行时间),则无需进行优化。我上面提到的优化是实际上实现的逻辑,该逻辑在每1us连续运行的系统中将代码执行速度提高了约60%。

  • 答案 3 :(得分:-4)

    实际上,在此示例中,语句之间的区别在于基本指令的数量:

    if (isActive && isResponding){
     //do this}
    

    在这里,CPU将计算isActive isResponding,而不是检查结果是否为0或1 否则,在其他代码中,他将做2检查如果在很长时间内多次重复执行 if 语句,则会发现性能差异  我希望我能帮忙