Versión larga...
Un compañero de trabajo afirmó hoy después de ver mi uso while (1)
en un script de Perl que for (;;)
es más rápido. Argumenté que deberían ser los mismos con la esperanza de que el intérprete optimizara cualquier diferencia. Configuré un script que ejecutaría 1,000,000,000 para iteraciones de bucles y la misma cantidad de bucles while y registraría el tiempo entre ellos. No pude encontrar una diferencia apreciable. Mi compañero de trabajo dijo que un profesor le había dicho que while (1)
estaba haciendo una comparación 1 == 1
y que for (;;)
no. Repetimos la misma prueba con 100x el número de iteraciones con C ++ y la diferencia fue insignificante. Sin embargo, fue un ejemplo gráfico de cuánto más rápido puede ser el código compilado frente a un lenguaje de script.
Version corta...
¿Hay alguna razón para preferir un while (1)
sobre a for (;;)
si necesita un bucle infinito para salir?
Nota: Si no está claro en la pregunta. Esta fue una discusión académica puramente divertida entre un par de amigos. Soy consciente de que este no es un concepto súper importante que todos los programadores deberían agonizar. Gracias por todas las excelentes respuestas que (y estoy seguro de que otros) he aprendido algunas cosas de esta discusión.
Actualización: el mencionado compañero de trabajo intervino con una respuesta a continuación.
Citado aquí en caso de que quede enterrado.
Provenía de un programador de ensamblaje de AMD. Afirmó que los programadores de C (la gente) no se dan cuenta de que su código tiene ineficiencias. Sin embargo, dijo hoy que los compiladores de gcc son muy buenos y dejan a personas como él fuera del negocio. Dijo por ejemplo, y me habló de la
while 1
frentefor(;;)
. Lo uso ahora por costumbre, pero gcc y especialmente los intérpretes harán la misma operación (un salto de procesador) durante estos dos días, ya que están optimizados.
fuente
Respuestas:
En perl, dan como resultado los mismos códigos de operación:
Asimismo en GCC:
Así que supongo que la respuesta es que son los mismos en muchos compiladores. Por supuesto, para algunos otros compiladores esto puede no ser necesariamente el caso, pero es probable que el código dentro del bucle sea unos miles de veces más costoso que el bucle en sí mismo, entonces, ¿a quién le importa?
fuente
Usando GCC, ambos parecen compilarse en el mismo lenguaje ensamblador:
fuente
No hay muchas razones para preferir uno sobre el otro. Creo que,
while(1)
y particularmente,while(true)
son más legibles quefor(;;)
, pero esa es solo mi preferencia.fuente
forever
es su propio token.No hay diferencia según el estándar. 6.5.3 / 1 tiene:
Y 6.5.3 / 2 tiene:
Entonces, de acuerdo con el estándar C ++, el código:
es exactamente lo mismo que:
fuente
El compilador de Visual C ++ solía emitir una advertencia para
(expresión constante) pero no para
Continué con la práctica de preferir
for (;;)
por esa razón, pero no sé si el compilador todavía lo hace en estos días.fuente
for(;;)
es un personaje menos para escribir si quieres ir en esa dirección para optimizar las cosas.fuente
Turbo C con estos viejos compiladores
for(;;)
resulta en un código más rápido entonceswhile(1)
.Hoy en día, los compiladores gcc, Visual C (creo que casi todos) se optimizan bien, y las CPU con 4.7 MHz rara vez se usan.
En aquellos días, a
for( i=10; i; i-- )
era más rápido quefor( i=1; i <=10; i++ )
, porque comparari
es 0, resulta en un salto condicional CPU-Zero-Flag. Y la Bandera Cero se modificó con la última operación de disminución( i-- )
, no se necesita ninguna operación cmp adicional.y aquí con
for(i=1; i<=10; i++)
cmpl extra:fuente
Para todas las personas que argumentan que no deberías usar bucles while indefinidos, y que sugieren cosas tontas como usar goto 's abiertos (en serio, ¡ay!)
Realmente no se puede representar efectivamente de otra manera. No sin crear una variable de salida y hacer magia negra para mantenerla sincronizada.
Si le gusta la sintaxis más goto-esque, use algo sensato que limite el alcance.
En última instancia, la velocidad no es tan importante
Preocuparse por cuán efectivas son las construcciones de bucle diferentes en cuanto a velocidad es una enorme pérdida de tiempo. Optimización prematura de principio a fin. No puedo pensar en ninguna situación que haya visto en la que el código de perfil encontró cuellos de botella en mi elección de construcción en bucle.
Generalmente es el cómo del bucle y el qué del bucle.
Debe "optimizar" la legibilidad y la concisión, y escribir lo que sea mejor para explicar el problema al próximo tonto que encuentre su código.
Si usa el truco "ir a LA ETIQUETA" que alguien mencionó, y tengo que usar su código, prepárese para dormir con un ojo abierto, especialmente si lo hace más de una vez, porque ese tipo de cosas crea un espantoso código de espagueti.
El hecho de que pueda crear código de espagueti no significa que deba
fuente
De Stroustrup, TC ++ PL (3a edición), §6.1.1:
Yo prefiero
for (;;)
.fuente
Si el compilador no realiza ninguna optimización,
for(;;)
siempre sería más rápido quewhile(true)
. Esto se debe a que while-instrucción evalúa la condición cada vez, pero for-instrucción es un salto incondicional. Pero si el compilador optimiza el flujo de control, puede generar algunos códigos de operación. Puede leer el código de desmontaje muy fácilmente.PD: podrías escribir un bucle infinito como este:
fuente
Escuché sobre esto una vez.
Provenía de un programador de ensamblaje de AMD. Dijo que los programadores de C (las personas) no se dan cuenta de que su código tiene ineficiencias. Sin embargo, dijo hoy que los compiladores de gcc son muy buenos y dejan a personas como él fuera del negocio. Dijo por ejemplo, y me habló de la
while 1
frentefor(;;)
. Lo uso ahora por costumbre, pero gcc y especialmente los intérpretes harán la misma operación (un salto de procesador) durante estos dos días, ya que están optimizados.fuente
En una compilación optimizada de un lenguaje compilado, no debería haber una diferencia apreciable entre los dos. Ninguno de los dos debe terminar realizando comparaciones en tiempo de ejecución, solo ejecutarán el código del bucle hasta que salga manualmente del bucle (por ejemplo, con a
break
).fuente
¡Me sorprende que nadie haya probado adecuadamente en
for (;;)
comparaciónwhile (1)
con Perl!Debido a que perl es un lenguaje interpretado, el tiempo para ejecutar un script perl no solo consiste en la fase de ejecución (que en este caso es la misma) sino también en la fase de interpretación antes de la ejecución. Ambas fases deben tenerse en cuenta al hacer una comparación de velocidad.
Afortunadamente, Perl tiene un conveniente módulo de referencia que podemos usar para implementar una referencia como la siguiente:
Tenga en cuenta que estoy probando dos versiones diferentes del bucle infinito: una que es más corta que el bucle while y otra que tiene un espacio adicional para que tenga la misma longitud que el bucle while.
En Ubuntu 11.04 x86_64 con perl 5.10.1 obtengo los siguientes resultados:
El ciclo while es claramente el ganador en esta plataforma.
En FreeBSD 8.2 x86_64 con perl 5.14.1:
Mientras que loop es el ganador aquí también.
En FreeBSD 8.2 i386 con perl 5.14.1:
¡Sorprendentemente, el bucle for con un espacio extra es la opción más rápida aquí!
Mi conclusión es que el ciclo while debe usarse en la plataforma x86_64 si el programador está optimizando la velocidad. Obviamente, se debe usar un bucle for al optimizar el espacio. Lamentablemente, mis resultados no son concluyentes con respecto a otras plataformas.
fuente
Benchmark
tiene sus limitaciones y no se puede usar para distinguir rápido de lento si los resultados están dentro del 7% entre sí. Además, no ha probado la diferencia entre los buclesfor
ywhile
porque cada sub lo harádie
antes de llegar a los bucles. ¿Y desde cuándo la cantidad de espacios en blanco era importante para el intérprete de Perl? Lo siento, pero el análisis es extremadamente defectuoso.die
Existe en mi código porque mi intención es probar solo la diferencia de tiempo de compilación . Como otros ya han señalado, el código de bytes resultante es idéntico, por lo tanto, no tiene sentido probar eso. Sorprendentemente, la cantidad de espacio en blanco parece hacer una pequeña diferencia en este caso en mis entornos de prueba. Que podría tener algo que ver con cómo los personajes terminan siendo alineado en la memoria o algo similar ...Benchmark
no son concluyentes. ¡No confíes en esa diferencia del 1% en absoluto!-60
ejecuta la prueba durante 60 segundos.En teoría, un compilador completamente ingenuo podría almacenar el literal '1' en el binario (pérdida de espacio) y verificar si 1 == 0 en cada iteración (pérdida de tiempo y más espacio).
En realidad, sin embargo, incluso con optimizaciones "no", los compiladores seguirán reduciendo ambos a la misma. También pueden emitir advertencias porque podría indicar un error lógico. Por ejemplo, el argumento de
while
podría definirse en otro lugar y no te das cuenta de que es constante.fuente
Me sorprende que nadie haya ofrecido la forma más directa, correspondiente al ensamblaje deseado:
fuente
{ forever: do stuff; goto forever; }
)while(1)
es un idioma para elfor(;;)
cual es reconocido por la mayoría de los compiladores.Me alegró ver que Perl también lo reconoce
until(0)
.fuente
Para resumir el debate
for (;;)
vswhile (1)
es obvio que el primero fue más rápido en los días de los compiladores no optimizadores más antiguos, es por eso que tiende a verlo en bases de código más antiguas, como los comentarios de código fuente de Lions Unix, sin embargo, en la era de la optimización rudo Los compiladores de esas ganancias se optimizan combinando eso con el hecho de que este último es más fácil de entender que el primero, creo que sería más preferible.fuente
Acabo de encontrar este hilo (aunque algunos años tarde).
Creo que encontré la razón real por la cual "for (;;)" es mejor que "while (1)".
de acuerdo con el "barr coding standard 2018"
Básicamente, este no es un problema de velocidad, sino un problema de legibilidad. Dependiendo de la fuente / impresión del código, el número uno (1) en un momento puede parecer una letra minúscula l.
es decir, 1 vs l. (en algunas fuentes se ven idénticas).
Por lo tanto, while (1) puede parecer un ciclo while dependiente de la letra variable L.
while (verdadero) también puede funcionar, pero en algunos casos antiguos de C y C incrustados, verdadero / falso aún no están definidos a menos que se incluya stdbool.h.
fuente
l
, no esa,1
yl
puede tener un aspecto similar.Creo que ambos son iguales en términos de rendimiento. Pero preferiría while (1) para facilitar la lectura, pero me pregunto por qué necesita un bucle infinito.
fuente
Ellos son iguales. Hay preguntas mucho más importantes para reflexionar.
Mi punto que estaba implícito pero no se hizo explícitamente arriba, es que un compilador decente generaría exactamente el mismo código para ambas formas de bucle. El punto más importante es que la construcción en bucle es una parte menor del tiempo de ejecución de cualquier algoritmo, y primero debe asegurarse de haber optimizado el algoritmo y todo lo demás relacionado con él. La optimización de su construcción de bucle debería estar absolutamente al final de su lista de prioridades.
fuente