performance - resueltos - la duracion maxima de patente para un nuevo medicamento es 17 años
¿Qué ciclo es más rápido, mientras o para? (16)
Puede obtener el mismo resultado con los bucles for y while:
Mientras:
$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?
Algunos compiladores de optimización podrán realizar un mejor despliegue de bucle con un bucle for, pero las probabilidades son que si está haciendo algo que se puede desenrollar, un compilador lo suficientemente inteligente como para desenrollarlo también sea lo suficientemente inteligente como para interpretar la condición de bucle de su mientras que el bucle también puede desenrollarse.
Como han dicho otros, cualquier compilador que merezca la pena generará un 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).
Deberían ser iguales. El bucle for que escribió está haciendo exactamente lo mismo que está haciendo el bucle while: establecer $i=0
, imprimir $i
e incrementar $i
al final del bucle.
Depende del idioma y muy probablemente de su compilador, pero deberían ser equivalentes en la mayoría de los idiomas.
En C #, el bucle For es ligeramente más rápido.
Para el promedio de bucle alrededor de 2.95 a 3.02 ms.
El ciclo While promedió alrededor de 3.05 a 3.37 ms.
Pequeña aplicación de 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");
}
}
En cuanto a los bucles infinitos for(;;)
bucle es mejor que while(1)
ya que while
evalúa cada vez la condición pero de nuevo depende del compilador.
Encuentro que el ciclo más rápido es un ciclo inverso, por ejemplo:
var i = myArray.length;
while(i--){
// Do something
}
Eso claramente depende de la implementación particular del intérprete / compilador del lenguaje específico.
Dicho esto, teóricamente, cualquier implementación sensata probablemente podrá 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, asumí y comporté como en C y en lenguajes similares. Podría crear un lenguaje con semántica completamente diferente para while
y for
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), definitivamente lo 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 la forma en que se itera.
Establezca las iteraciones de bucle en 10,000.
Encuentre el tiempo en milisegundos> Ejecutar bucle> encuentre 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 obtengas momentos muy similares en ambos, pero estoy interesado en ver si uno siempre es un poco más rápido.
Me preguntaba lo mismo, así que busqué en Google y terminé aquí. Hice una pequeña prueba en python (extremadamente simple) solo para ver y esto es lo que obtuve:
Por:
def for_func(n = 0):
for n in range(500):
n = n + 1
python -m timeit "import for_func; for_func.for_func ()"> for_func.txt
10000 loops, el mejor de 3: 40.5 usec por ciclo
Mientras:
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 bucles, el mejor de 3: 45 usec por bucle
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 también podrían ser útiles: Cómo escribir un código más eficiente
No es un bucle For técnicamente un Do While?
P.ej
for (int i = 0; i < length; ++i)
{
//Code Here.
}
sería...
int i = 0;
do
{
//Code Here.
} while (++i < length);
Aunque podría estar equivocado ...
También cuando se trata de 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();
}
debería ser más rápido que ...
for (int i = 0; i < data.length; ++i)
{
data[i].doSomething();
}
Si ese 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í.
También traté de comparar los diferentes tipos de bucle en C #. Usé el mismo código que Shane , pero también probé con un do-while y descubrí que era el más rápido. Este es el 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");
}
}
y estos son los resultados de una demostración en vivo en DotNetFiddle :
Do While Loop:
00: 00: 00.06Mientras que Loop:
00: 00: 00.13En bucle:
00: 00: 00.27
Usé un bucle for y while en una máquina de prueba sólida (no se ejecutan procesos de fondo de terceros no estándar). Ejecuté un for loop
vs while loop
en lo que respecta a cambiar la propiedad de estilo de 10.000 nodos <button>
.
La prueba se ejecutó consecutivamente 10 veces, con 1 ejecución agotada por 1500 milisegundos antes de la ejecución:
Aquí está el javascript muy simple 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í están 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 enlace de demostración
Actualizar
A continuación, se encuentra una prueba separada que he llevado a cabo, que implementa 2 algoritmos factoriales escritos de manera diferente, 1 usando un ciclo for, mientras que el otro usa un ciclo 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 para el benchmark 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ífico probado, no hay un ganador claro en términos de rendimiento entre un tiempo y para el ciclo. Pruebas realizadas en MacAir con OS X Mavericks en Chrome Evergreen.