哪个循环更快,而对于?

时间:2010-09-02 16:32:53

标签: performance for-loop while-loop

您可以使用for和while循环获得相同的输出:

虽然:

$i = 0;
while ($i <= 10){
  print $i."\n";
  $i++;
};

:用于:

for ($i = 0; $i <= 10; $i++){
  print $i."\n";
}

但哪一个更快?

17 个答案:

答案 0 :(得分:22)

这显然取决于特定语言的解释器/编译器的特定实现。

也就是说,从理论上讲,任何理智的实现都可能能够在另一个实现方面实现一个,如果它更快,那么差异最多可以忽略不计。

当然,我假设whilefor的行为与C和类似语言中的行为相同。您可以为whilefor 创建一种语义完全不同的语言

答案 1 :(得分:12)

在C#中, For循环稍快一些。

对于环路平均值约为2.95到3.02 ms。

While循环的平均值约为3.05至3.37毫秒。

快速的小控制台应用程序来证明:

 class Program
    {
        static void Main(string[] args)
        {
            int max = 1000000000;
            Stopwatch stopWatch = new Stopwatch();

            if (args.Length == 1 && args[0].ToString() == "While")
            {
                Console.WriteLine("While Loop: ");
                stopWatch.Start();
                WhileLoop(max);
                stopWatch.Stop();
                DisplayElapsedTime(stopWatch.Elapsed);
            }
            else
            {
                Console.WriteLine("For Loop: ");
                stopWatch.Start();
                ForLoop(max);
                stopWatch.Stop();
                DisplayElapsedTime(stopWatch.Elapsed);
            }
        }

        private static void WhileLoop(int max)
        {
            int i = 0;
            while (i <= max)
            {
                //Console.WriteLine(i);
                i++;
            };
        }

        private static void ForLoop(int max)
        {
            for (int i = 0; i <= max; i++)
            {
                //Console.WriteLine(i);
            }
        }

        private static void DisplayElapsedTime(TimeSpan ts)
        {
            // Format and display the TimeSpan value.
            string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
                ts.Hours, ts.Minutes, ts.Seconds,
                ts.Milliseconds / 10);
            Console.WriteLine(elapsedTime, "RunTime");
        }
    }

答案 2 :(得分:6)

我发现最快的循环是反向循环,例如:

var i = myArray.length;
while(i--){
  // Do something
}

答案 3 :(得分:5)

正如其他人所说的,任何有价值的编译器都会产生几乎相同的代码。任何性能差异都可以忽略不计 - 您是微观优化的。

真正的问题是,什么更具可读性?这就是for循环(至少是恕我直言)。

答案 4 :(得分:3)

如果那是C程序,我也不会说。编译器将输出完全相同的代码。既然不是,我说要衡量它。实际上,这不是关于哪个循环结构更快,因为这是一个微不足道的时间节省。这是关于哪个循环结构更容易维护。在你展示的情况下,for循环更合适,因为它是其他程序员(包括未来你,希望)希望在那里看到的。

答案 5 :(得分:3)

将循环迭代设置为10,000。

以毫秒为单位查找时间&gt;以毫秒为单位运行循环&gt;查找时间并减去第一个计时器。

为两个代码执行此操作,无论哪个代码具有运行速度最快的最短毫秒数。您可能希望多次运行测试并将其平均以减少后台进程影响测试的可能性。

你可能会在两者上得到非常相似的时间,但我很想知道一个人是否总是稍快一点​​。

答案 6 :(得分:1)

他们应该是平等的。您编写的for循环与while循环执行的操作完全相同:设置$i=0,打印$i,并在循环结束时递增$i

答案 7 :(得分:1)

一些优化编译器将能够使用for循环更好地循环展开,但是如果你正在做一些可以展开的东西,那么一个足够聪明的编译器可能也足够聪明地解释循环你的while循环的条件也可以展开。

答案 8 :(得分:1)

我在一台实体测试机器上使用了for和while循环(没有运行非标准的第三方后台进程)。我运行了for loop vs while loop,因为它与更改10,000 <button>个节点的样式属性有关。

测试连续运行10次,1次运行超时1500毫秒,然后执行:

以下是我为此目的制作的非常简单的javascript

function runPerfTest() {
    "use strict";

    function perfTest(fn, ns) {
        console.time(ns);
        fn();
        console.timeEnd(ns);
    }

    var target = document.getElementsByTagName('button');

    function whileDisplayNone() {
        var x = 0;
        while (target.length > x) {
            target[x].style.display = 'none';
            x++;
        }
    }

    function forLoopDisplayNone() {
        for (var i = 0; i < target.length; i++) {
            target[i].style.display = 'none';
        }
    }

    function reset() {
        for (var i = 0; i < target.length; i++) {
            target[i].style.display = 'inline-block';
        }
    }

    perfTest(function() {
        whileDisplayNone();
    }, 'whileDisplayNone');

    reset();

    perfTest(function() {
        forLoopDisplayNone();
    }, 'forLoopDisplayNone');

    reset();
};

$(function(){
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    setTimeout(function(){
        console.log('cool run');
        runPerfTest();
    }, 1500);
});

以下是我得到的结果

pen.js:8 whileDisplayNone: 36.987ms
pen.js:8 forLoopDisplayNone: 20.825ms

pen.js:8 whileDisplayNone: 19.072ms
pen.js:8 forLoopDisplayNone: 25.701ms

pen.js:8 whileDisplayNone: 21.534ms
pen.js:8 forLoopDisplayNone: 22.570ms

pen.js:8 whileDisplayNone: 16.339ms
pen.js:8 forLoopDisplayNone: 21.083ms

pen.js:8 whileDisplayNone: 16.971ms
pen.js:8 forLoopDisplayNone: 16.394ms

pen.js:8 whileDisplayNone: 15.734ms
pen.js:8 forLoopDisplayNone: 21.363ms

pen.js:8 whileDisplayNone: 18.682ms
pen.js:8 forLoopDisplayNone: 18.206ms

pen.js:8 whileDisplayNone: 19.371ms
pen.js:8 forLoopDisplayNone: 17.401ms

pen.js:8 whileDisplayNone: 26.123ms
pen.js:8 forLoopDisplayNone: 19.004ms

pen.js:61 cool run
pen.js:8 whileDisplayNone: 20.315ms
pen.js:8 forLoopDisplayNone: 17.462ms

以下是demo link

<强>更新

我所进行的单独测试位于下方,它实现了2种不同的写法因子算法,1使用for循环,另一种使用while循环。

以下是代码:

function runPerfTest() {
    "use strict";

    function perfTest(fn, ns) {
        console.time(ns);
        fn();
        console.timeEnd(ns);
    }

    function whileFactorial(num) {
        if (num < 0) {
            return -1;
        }
        else if (num === 0) {
            return 1;
        }
        var factl = num;
        while (num-- > 2) {
            factl *= num;
        }
        return factl;
    }

    function forFactorial(num) {
        var factl = 1;
        for (var cur = 1; cur <= num; cur++) {
            factl *= cur;
        }
        return factl;
    }

    perfTest(function(){
        console.log('Result (100000):'+forFactorial(80));
    }, 'forFactorial100');

    perfTest(function(){
        console.log('Result (100000):'+whileFactorial(80));
    }, 'whileFactorial100');
};

(function(){
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    console.log('cold run @1500ms timeout:');
    setTimeout(runPerfTest, 1500);
})();

和阶乘基准的结果:

pen.js:41 Result (100000):7.15694570462638e+118
pen.js:8 whileFactorial100: 0.280ms
pen.js:38 Result (100000):7.156945704626378e+118
pen.js:8 forFactorial100: 0.241ms
pen.js:41 Result (100000):7.15694570462638e+118
pen.js:8 whileFactorial100: 0.254ms
pen.js:38 Result (100000):7.156945704626378e+118
pen.js:8 forFactorial100: 0.254ms
pen.js:41 Result (100000):7.15694570462638e+118
pen.js:8 whileFactorial100: 0.285ms
pen.js:38 Result (100000):7.156945704626378e+118
pen.js:8 forFactorial100: 0.294ms
pen.js:41 Result (100000):7.15694570462638e+118
pen.js:8 whileFactorial100: 0.181ms
pen.js:38 Result (100000):7.156945704626378e+118
pen.js:8 forFactorial100: 0.172ms
pen.js:41 Result (100000):7.15694570462638e+118
pen.js:8 whileFactorial100: 0.195ms
pen.js:38 Result (100000):7.156945704626378e+118
pen.js:8 forFactorial100: 0.279ms
pen.js:41 Result (100000):7.15694570462638e+118
pen.js:8 whileFactorial100: 0.185ms
pen.js:55 cold run @1500ms timeout:
pen.js:38 Result (100000):7.156945704626378e+118
pen.js:8 forFactorial100: 0.404ms
pen.js:41 Result (100000):7.15694570462638e+118
pen.js:8 whileFactorial100: 0.314ms

结论:无论测试的样本大小或特定任务类型,在while和for循环之间的性能方面都没有明显的优势。在Chrome常青树上使用OS X Mavericks在MacAir上进行测试。

答案 9 :(得分:0)

for 循环比使用 OpenMP 之类的 while 循环更容易并行化

因此,如果循环中的代码足够耗时,请使用 for 循环并将其并行化。

对于简短的代码片段,您不希望并行化,因为启动另一个线程(一项昂贵的操作)比简单地完成循环需要更长的时间..所以任何一个似乎都差不多来自其他答案。

答案 10 :(得分:0)

我还尝试在C#中对不同类型的循环进行基准测试。我使用the same code as Shane,但我也尝试了一段时间,发现它是最快的。这是代码:

using System;
using System.Diagnostics;


public class Program
{
    public static void Main()
    {
        int max = 9999999;
        Stopwatch stopWatch = new Stopwatch();

        Console.WriteLine("Do While Loop: ");
        stopWatch.Start();
        DoWhileLoop(max);
        stopWatch.Stop();
        DisplayElapsedTime(stopWatch.Elapsed);
        Console.WriteLine("");
        Console.WriteLine("");

        Console.WriteLine("While Loop: ");
        stopWatch.Start();
        WhileLoop(max);
        stopWatch.Stop();
        DisplayElapsedTime(stopWatch.Elapsed);
        Console.WriteLine("");
        Console.WriteLine("");

        Console.WriteLine("For Loop: ");
        stopWatch.Start();
        ForLoop(max);
        stopWatch.Stop();
        DisplayElapsedTime(stopWatch.Elapsed);
    }

    private static void DoWhileLoop(int max)
    {
        int i = 0;
        do
        {
            //Performe Some Operation. By removing Speed increases
            var j = 10 + 10;
            j += 25;
            i++;
        } while (i <= max);
    }

    private static void WhileLoop(int max)
    {
        int i = 0;
        while (i <= max)
        {
            //Performe Some Operation. By removing Speed increases
            var j = 10 + 10;
            j += 25;
            i++;
        };
    }

    private static void ForLoop(int max)
    {
        for (int i = 0; i <= max; i++)
        {
            //Performe Some Operation. By removing Speed increases
            var j = 10 + 10;
            j += 25;
        }
    }

    private static void DisplayElapsedTime(TimeSpan ts)
    {
        string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10);
        Console.WriteLine(elapsedTime, "RunTime");
    }
}

这些是live demo on DotNetFiddle

的结果
  

Do While Loop:
  00:00:00.06

     

While Loop:
  00:00:00.13

     

For Loop:
  00:00:00.27

答案 11 :(得分:0)

至于无限循环for(;;)循环优于while(1),因为while每次条件时都会计算,但它又取决于编译器。

答案 12 :(得分:0)

我想知道同样的事情,所以我用Google搜索并最终到了这里。 我在python中做了一个小测试(非常简单)只是为了看看,这就是我得到的:

:用于:

def for_func(n = 0):
    for n in range(500):
        n = n + 1
  

python -m timeit&#34; import for_func; for_func.for_func()&#34; &GT; for_func.txt

     

10000循环,最佳3:40.5 usec每循环

<强>虽然:

def while_func(n = 0):
    while n < 500:
        n = n + 1
  

python -m timeit&#34; import while_func; while_func.while_func()&#34; &GT; while_func.txt

     

10000个循环,最好是每个循环3:45 usec

答案 13 :(得分:0)

技术上不是For循环吗?

E.g。

for (int i = 0; i < length; ++i)
{
   //Code Here.
}

会......

int i = 0;
do 
{
  //Code Here.
} while (++i < length);

我可能错了......

也适用于for循环。如果您计划仅检索数据而从不修改数据,则应使用foreach。如果由于某种原因需要实际索引,则需要增加,因此应使用常规for循环。

for (Data d : data)
{
       d.doSomething();
}

应该比...更快

for (int i = 0; i < data.length; ++i)
{
      data[i].doSomething();
}

答案 14 :(得分:0)

这将取决于所述循环,编译器的语言实现,以及什么不是。

大多数编译器将编译为完全相同的可执行代码,例如在CIL(.NET)中他们肯定会这样做。

来源:vcsjones @ http://forums.asp.net/t/1041090.aspx

无论哪种方式,循环体都是处理时间而不是迭代方式。

答案 15 :(得分:0)

哪个更快更重要。如果它确实重要,那么使用您的真实代码对其进行基准测试,并亲自看看。

这个问题的答案也许有用:How to write more efficient code

答案 16 :(得分:0)

取决于语言,很可能取决于它的编译器,但它们在大多数语言中应该是等价的。