ti-enxame.com

Qual loop é mais rápido, enquanto ou para?

Você pode obter a mesma saída com loops for e while:

Enquanto:

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

Para:

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

Mas qual deles é mais rápido?

28
Mark Lalor

Isso depende claramente da implementação particular do interpretador/compilador da linguagem específica.

Dito isso, teoricamente, qualquer implementação sensata provavelmente será capaz de implementar uma em termos da outra se fosse mais rápida, de modo que a diferença deveria ser insignificante no máximo. 

É claro que assumi que while e for se comportam como em C e em linguagens similares. Você poderia criar uma linguagem com semântica completamente diferente para while e for

21
Mehrdad Afshari

Em C #, o loop For é ligeiramente mais rápido. 

Para média de loop de 2,95 a 3,02 ms. 

O loop While tinha uma média de 3,05 a 3,37 ms.

App pequeno console rápido para provar:

 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");
        }
    }
12
Shane

Eu acho que o loop mais rápido é um loop reverso, por exemplo:

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

Como outros já disseram, qualquer compilador que valha a pena gerará código praticamente idêntico. Qualquer diferença no desempenho é insignificante - você está otimizando o micro.

A verdadeira questão é: o que é mais legível? E esse é o loop for (pelo menos IMHO).

4
Aillyn

Se isso fosse um programa em C, eu diria que não. O compilador irá produzir exatamente o mesmo código. Como não é, digo medir. Na verdade, não é sobre qual construção de loop é mais rápida, já que é uma quantidade minúscula de economia de tempo. É sobre qual construção de loop é mais fácil de manter. No caso que você mostrou, um loop for é mais apropriado porque é o que outros programadores (incluindo o futuro você, esperançosamente) esperarão ver lá.

3
nmichaels

Defina as iterações do loop para 10.000. 

Encontre a hora em milissegundos> Executar Loop> encontre o tempo em milissegundos e subtraia o primeiro temporizador.

Faça isso para os dois códigos, o que quer que tenha os milissegundos mais baixos que ele executa mais rapidamente. Você pode querer executar o teste várias vezes e calculá-las para reduzir a probabilidade de processos em segundo plano influenciarem o teste.

É provável que você tenha momentos muito parecidos em ambos, mas estou interessado em ver se um é sempre um pouco mais rápido.

3
AttackingHobo

Eu usei um loop for e while em uma máquina de teste sólida (sem processos em segundo plano não padrão em execução). Eu corri um for loop vs while loop como se relaciona com a alteração da propriedade de estilo de 10.000 <button> nós.

O teste foi executado consecutivamente 10 vezes, com 1 execução expirada por 1.500 milissegundos antes da execução:

Aqui está o javascript muito simples que fiz para este propósito

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);
});

Aqui estão os resultados que eu tenho

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

Aqui está o link de demonstração

Atualizar

Um teste separado que realizei está localizado abaixo, que implementa 2 algoritmos fatoriais escritos de forma diferente, 1 usando um loop for, o outro usando um loop while.

Aqui está o código:

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);
})();

E os resultados para o benchmark fatorial:

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

Conclusão: Não importa o tamanho da amostra ou o tipo de tarefa específica testada, não há um vencedor claro em termos de desempenho entre while e for loop. Teste feito em um MacAir com OS X Mavericks no Chrome evergreen.

1
Alpha G33k

Alguns compiladores otimizadores poderão fazer um melhor loop de desenrolamento com um loop for, mas as probabilidades são de que se você estiver fazendo algo que pode ser desenrolado, um compilador inteligente o bastante para desenrolá-lo provavelmente também é inteligente o suficiente para interpretar a condição de loop de seu loop. while loop como algo que pode desenrolar também.

1
Chris

Eles devem ser iguais. O loop for que você escreveu está fazendo exatamente a mesma coisa que o loop while está fazendo: configurando $i=0, imprimindo $i e incrementando $i no final do loop.

1
murgatroid99

Eu também tentei benchmark os diferentes tipos de loop em c #. Eu usei o mesmo código que Shane , mas eu também tentei com um do-while e achei que fosse o mais rápido. Este é o código:

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");
    }
}

e estes são os resultados de um live demo no DotNetFiddle

Do While Loop:
00: 00: 00.06

While Loop:
00: 00: 00.13

For Loop:
00: 00: 00.27

0
Mohit Dhawan

Quanto aos loops infinitos, for(;;) loop é melhor que while(1), já que while avalia cada vez que a condição, mas novamente, depende do compilador.

0
Ilian Zapryanov

Depende da linguagem e provavelmente do seu compilador, mas eles devem ser equivalentes na maioria das linguagens. 

0
Randolpho

Eu estava me perguntando a mesma coisa, então eu pesquisei e acabei aqui. Eu fiz um pequeno teste em python (extremamente simples) só para ver e é isso que eu recebi:

Para:

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

python -m timeit "importação for_func; for_func.for_func ()"> for_func.txt

10000 voltas, melhor de 3: 40.5 usec por loop

Enquanto:

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

python -m timeit "import while_func; while_func.while_func ()"> while_func.txt

10000 voltas, melhor de 3: 45 usec por loop

0
niclaslindgren

Não importa o que é mais rápido. Se isso importa, faça um benchmark usando seu código real e veja por si mesmo.

As respostas para essa outra pergunta também podem ser úteis: Como escrever código mais eficiente

0
David

Isso dependerá da implementação da linguagem do referido loop, compilador e quais não. 

A maioria dos compiladores compilará exatamente o mesmo código executável, por exemplo, no CIL (.NET). 

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

De qualquer maneira, o corpo do loop é onde o tempo de processamento será gasto não da maneira como você iterar. 

0
jfrobishow

Não é um For Loop tecnicamente um Do While?

Por exemplo.

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

seria...

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

Eu posso estar errado embora ...

Além disso, quando se trata de loops for. Se você planeja apenas recuperar dados e nunca modificar dados, você deve usar um foreach. Se você precisar dos índices reais por algum motivo, precisará incrementar, portanto, você deve usar o loop for regular.

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

deve ser mais rápido que ...

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