2010-09-02 30 views
25

, usted puede obtener el mismo resultado con for y while:¿Qué ciclo es más rápido, mientras o para?

bien:

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

Por:

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

Pero, ¿cuál es más rápido?

+7

Mídelos si lo desea (pero probablemente sean iguales). –

+3

Te apuesto que generan exactamente el mismo código de bytes. – zwol

+5

'for' en la mayoría de los lenguajes es azúcar sintáctico para un ciclo' while 'equivalente, que a su vez es azúcar sintáctico para un conjunto de etiquetas y 'gotos' para ensamblar o IL. Dada una implementación eficiente de la especificación de idioma, estos serán aproximadamente iguales. Algunos lenguajes incluyen "comentarios" internos que dan pistas sobre descompiladores/reflectores sobre el aspecto del código original, lo que tendrá un efecto insignificante en el rendimiento. Creo que encontrará que las mayores diferencias de tiempo de ejecución entre estos son inherentes a la programación del sistema operativo. – KeithS

Respuesta

20

Eso claramente depende de la implementación particular del intérprete/compilador del idioma específico.

Dicho esto, teóricamente, cualquier aplicación en su sano juicio será capaz de implementar una en términos de la otra si fuera más rápida, por lo que la diferencia debería ser insignificante como máximo.

Por supuesto, supuse que while y for se comportan como lo hacen en C y en otros idiomas similares. Puede crear un lenguaje con semántica completamente diferente para while y for

0

Depende del idioma y muy probablemente de su compilador, pero deben ser equivalentes en la mayoría de los idiomas.

1

Deben ser iguales. El bucle for que escribió está haciendo exactamente lo mismo que el bucle while: configuración $i=0, impresión de $i e incremento de $i al final del bucle.

3

Si fuera un programa C, yo diría que ninguno. El compilador generará exactamente el mismo código. Como no es así, digo medirlo. Realmente, no se trata de qué construcción de bucle es más rápida, ya que es una cantidad minúscula de ahorro de tiempo. Se trata de qué construcción de bucle es más fácil de mantener. En el caso que mostró, un bucle for es más apropiado porque es lo que otros programadores (incluido el futuro, con suerte) esperarán ver allí.

0

No debería importar cuál es más rápido. Si no importa, compárelo con su código real y compruébelo usted mismo.

Las respuestas a esta otra pregunta podría ser útil también: How to write more efficient code

0

Eso dependerá de la implementación del lenguaje de dicho bucle, compilador y lo que no.

La mayoría de los compiladores compilarán exactamente el mismo código ejecutable, por ejemplo en CIL (.NET) que definitivamente hacen.

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

De cualquier manera, el cuerpo del bucle es donde se gastará el tiempo de procesamiento no de la manera que usted repite.

3

Establezca las iteraciones de bucle en 10,000.

Busca el tiempo en milisegundos> Ejecutar bucle> encuentra el tiempo en milisegundos y reste el primer temporizador.

Hazlo para ambos códigos, cualquiera que tenga los milisegundos más bajos se ejecuta más rápido. Es posible que desee ejecutar la prueba varias veces y promediarlas para reducir la probabilidad de que los procesos de fondo influyan en la prueba.

Es probable que obtenga tiempos realmente similares en ambos, pero estoy interesado en ver si uno siempre es un poco más rápido.

+0

Sorprendentemente, para PHP, el ciclo while fue 0.08 segundos más rápido en 10 millones de iteraciones. –

4

Como han dicho otros, cualquier compilador digno de su sal generará código prácticamente idéntico. Cualquier diferencia en el rendimiento es insignificante: usted está optimizando en micro.

La verdadera pregunta es, ¿qué es más legible? Y ese es el ciclo for (al menos en mi humilde opinión).

5

encuentro el bucle más rápido es un bucle while inversa, por ejemplo:

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

En C#, el bucle For es un poco más rápido.

Para bucle promedio de aproximadamente 2.95 a 3.02 ms.

El ciclo While promedió alrededor de 3.05 a 3.37 ms.

aplicación pequeña consola rápida para probar:

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

Puede ser posible que cuando el compilador se estaba ejecutando durante el ciclo ejecutó alguna otra tarea de fondo, y de eso tomó un poco más de tiempo. ¿Cómo te aseguraste de esas cosas? –

+0

No lo hice. Este no fue un experimento de sala limpia. Realicé este mismo proceso muchas veces y consistentemente obtendría resultados similares. Así que eso me dice que la probabilidad de que alguna tarea en segundo plano afecte aleatoriamente los tiempos solo para While Loop fue mínima. – Shane

+1

Lo que es más rápido depende de lo que está iterando. [Aquí hay una comparación de blogs que compara iteraciones] (http://cc.davelozinski.com/c-sharp/for-vs-foreach-vs-while) sobre múltiples tipos de objetos, como DataRows y objetos personalizados, que también incluyen el el rendimiento de la construcción del ciclo While y no solo las construcciones for y foreach. –

1

Algunos compiladores de optimización serán capaces de hacerlo mejor bucle de desenrollar con un bucle, pero las probabilidades son que si usted está haciendo algo que puede ser desenrollado, una un compilador lo suficientemente inteligente como para desenrollarlo probablemente también sea lo suficientemente inteligente como para interpretar la condición de bucle de su ciclo while como algo que también puede desenrollar.

0

¿No es técnicamente útil un ciclo For For?

E.g.

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

sería ...

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

Podría estar equivocado, aunque ...

También cuando se trata de los bucles. Si planea solo recuperar datos y nunca modificar los datos, debe usar un foreach. Si necesita los índices reales por algún motivo, deberá aumentar, por lo que debe usar el ciclo for for normal.

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

debe ser más rápido que ...

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

Un bucle 'for' no es un bucle' do'. Una prueba antes de la ejecución del ciclo y la otra después. Gran diferencia. –

0

Me preguntaba lo mismo por lo que busqué en Google y terminamos aquí. hice una pequeña prueba en Python (extremadamente simple) sólo para ver y esto es lo que tengo:

Por:

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

python -m timeit "for_func importación; for_func.for_func() "> for_func.txt

10000 loops, lo mejor de 3: 40.5 USEC por lazo

bien:

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

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

10.000 bucles, lo mejor de 3: 45 usec por ciclo

1

Utilicé un ciclo for y while en un sólido máquina de prueba (no se ejecutan procesos de fondo de terceros no estándar). Ejecuté un for loop frente a while loop en lo que respecta a cambiar la propiedad de estilo de 10,000 <button> nodos.

La prueba se llevó a cabo de forma consecutiva 10 veces, con 1 carrera el tiempo de espera para 1500 milisegundos antes de la ejecución:

Aquí es el muy simple javascript que hice 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); 
}); 

Aquí son los resultados que obtuve

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 

Aquí está el demo link

actualización

Una prueba separada he llevado a cabo se encuentra debajo, que implementa 2 algoritmos factoriales diferente escritas, 1 utilizando un bucle, el otro que utiliza un bucle while.

Aquí está el 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); 
})(); 

Y los resultados de la prueba patrón factorial:

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 

Conclusión: No importa el tamaño de la muestra o el tipo de tarea específica de la prueba, no hay un claro ganador en términos de rendimiento entre un tiempo y para bucle. Pruebas realizadas en MacAir con OS X Mavericks en Chrome Evergreen.

+0

Entonces, ¿cuál es su conclusión? – Bergi

+0

Aumentaré el tamaño de la muestra y usaré un algoritmo para la próxima carga de proceso en lugar de esto. Con suerte, los resultados serán más concluyentes en ese momento. Solo estoy buscando la implementación correcta para extender esto correctamente. –

+1

@Bergi No hay ganador claro después de más pruebas –

0

En cuanto a los bucles infinitos for(;;) bucle es mejor que while(1) desde while evalúa cada vez que la condición pero de nuevo depende del compilador.

Cuestiones relacionadas