2009-05-22 9 views
23

He estado codificando en C++ durante mucho tiempo. Siempre me he preguntado cuál tiene una velocidad de ejecución más rápida printf o cout?cout o printf ¿cuál de las dos tiene una velocidad de ejecución más rápida C++?

Situación: Estoy diseñando una aplicación en C++ y tengo ciertas limitaciones, como el límite de tiempo para la ejecución. Mi aplicación tiene muchos comandos de impresión en la consola. Entonces, ¿cuál sería preferible printf o cout?

+0

manzanas o naranjas: que son más sabrosos? – bk1e

+5

Si es importante para usted, escriba una aplicación pequeña que haga las dos cosas y la hora. Eso debería llevarte los 15 minutos para hacer. –

+3

@Neil: no es * que * simple. std :: cout y operator << causan que se emita más código en el momento de la llamada. Toda la lógica de printf se encuentra en el CRT, pero utiliza la lógica de tiempo de ejecución para interpretar la cadena del argumento. Por lo tanto, los programas grandes con muchos sitios de llamadas y muchas directivas de formato diferentes pueden ver diferentes efectos que un pequeño programa de prueba con solo un gran 'por (mucho) {printf ("% d ", i); } ' – MSalters

Respuesta

21

Cada uno tiene sus propios gastos generales. Dependiendo de lo que imprima, cualquiera puede ser más rápido.

Aquí hay dos puntos que vienen a la mente -

printf() tiene que analizar el "formato" cadena y actuar en consecuencia, lo que añade un costo.
cout tiene una jerarquía de herencia más compleja y pasa alrededor de los objetos.

En la práctica, la diferencia no debería importar para todos excepto para los casos más extraños. Si crees que realmente importa, ¡mide!

EDITAR-
Oh, diablos, no creo que esté haciendo esto, pero para que conste, en mi caso de prueba muy específica, con mi máquina muy específica y su carga muy específica, en la compilación Suelte usando MSVC -

Impresión 150,000 "Hello, World!" S (sin usar endl) toma aproximadamente -
90ms para printf(), 79ms para cout.

Impresión 150,000 dobles al azar toma aproximadamente -
3450ms para printf(), 3420ms para cout.

(promediada en 10 ejecuciones).

Las diferencias son tan escasas que esto probablemente no significa nada ...

+1

Ni una jerarquía de herencia compleja ni los objetos que pasan por sí mismos inducen gastos generales. –

+3

Una jerarquía de herencia compleja generalmente significa menos localidad, lo que es un impacto en el rendimiento. Y pasar objetos alrededor, bueno, pasa objetos que no se hubieran pasado de otra forma ... Pero estoy completamente de acuerdo en que estos son anecdóticos. – Hexagon

+0

Ahí lo tenemos. Su punto de referencia rápido muestra que la diferencia es realmente insignificante: la pequeña ventaja que posiblemente se podría haber obtenido por otros medios, o algo específico para la situación, incluso. – Noldorin

25

lo que realmente necesita para cuidar que tiene una velocidad de ejecución más rápido? Ambos se usan simplemente para imprimir texto en la consola/stdout, que normalmente no es una tarea que exige una eficiencia ultraelevada. Para el caso, no me imagino que haya una gran diferencia en la velocidad de todos modos (aunque podría esperar printf ser marginalmente más rápido porque carece de las complicaciones menores de orientación a objetos). Sin embargo, dado que estamos lidiando con operaciones de E/S aquí, incluso una pequeña diferencia probablemente se vea saturada por la sobrecarga de E/S. Ciertamente, si comparas los métodos equivalentes para escribir en archivos, ese sería el caso.

printf es simplemente la forma estándar de texto de salida a la salida estándar en C.
'cout' tuberías es simplemente la forma estándar de texto de salida a la salida estándar en C++.

Dicho todo esto, hay un hilo en el grupo comp.lang.cc que analiza el mismo tema. Sin embargo, el consenso parece ser que debe elegir uno sobre el otro por razones distintas al rendimiento.

+16

+1 para señalar que no importa. – paxdiablo

+10

No llegaría tan lejos como para decir que no importa.Ciertamente, puedo imaginar casos en los que aparece (cuando se escriben millones de líneas de líneas de registro, por ejemplo). Pero serían pocos y distantes. – Hexagon

+0

@Hexagon: si ese es el caso, lo más probable es que esté iniciando sesión en un archivo o utilizando un sistema de registro personalizado, en cuyo caso obtendrá un muy buen rendimiento de todos modos. – Noldorin

6

En Windows al menos, escribir en la consola es un gran cuello de botella, por lo que un programa de modo de consola "ruidoso" será mucho más lento que uno silencioso. Entonces, en esa plataforma, las ligeras diferencias en las funciones de la biblioteca utilizadas para abordar la consola probablemente no harán una diferencia significativa en la práctica.

En otras plataformas, puede ser diferente. También depende de la cantidad de salida de la consola que está haciendo, en relación con otro trabajo útil.

Por último, depende de la implementación de su plataforma de las bibliotecas de C y C++ de E/S.

lo que no hay una respuesta general a esta pregunta.

+0

total +1 en esto. Tenía un programa de prueba escupiendo mucha información de registro en stdout. En la ventana de consola normal en Windows, se ejecuta durante 15 minutos. Si oculto la ventana, se ejecuta en 5 minutos. Lo mismo puede aplicar Konsole en KDE si está en Linux. Sugiero que reduzca la cantidad de datos impresos de stdout/stderr, y use un archivo de registro en su lugar para obtener información detallada, mantenga la consola al mínimo. Afortunadamente, este programa de consola es muy eficiente: http://sourceforge.net/projects/console –

2

En términos prácticos, siempre he encontrado printf ser más rápido que cout. Pero, de nuevo, cout hace mucho más por ti en términos de seguridad de tipo. Recuerde también que printf es una función simple, mientras que cout es un objeto basado en una jerarquía compleja de flujos, por lo que no es realmente justo comparar los tiempos de ejecución.

+0

Supongo que estoy de acuerdo con que su punto cout hace mucho más que prinft. Hice esta pregunta por curiosidad y no para compararlos. Muchas gracias :) – pirate

4

El rendimiento no es un problema para la comparación; No se puede pensar en nada donde realmente cuente (desarrollar un programa de consola). Sin embargo, hay algunos puntos que debe tener en cuenta:

  • Iostreams operador uso de encadenamiento en lugar de va_args. Esto significa que su programa no se puede bloquear porque pasó una cantidad incorrecta de argumentos. Esto puede suceder con printf.

  • Iostreams usa la sobrecarga del operador en lugar de va_args - esto significa que su programa no se puede bloquear porque pasó una int y esperaba una cadena. Esto puede suceder con printf.

  • Iostreams no tienen soporte nativo para las cadenas de formato (que es la principal causa de # 1 y # 2). Esto generalmente es algo bueno, pero a veces son útiles. La biblioteca de formato Boost brinda esta funcionalidad a Iostreams para aquellos que lo necesitan con un comportamiento definido (arroja una excepción) en lugar de un comportamiento indefinido (como es el caso de printf). Esto actualmente está fuera del estándar.

  • Iostreams, a diferencia de sus equivalentes printf, pueden manejar los búferes de longitud variable directamente ellos mismos en lugar de estar obligados a tratar con cruco codificado.

Vaya para cout.

1

Si alguna vez tiene que descubrir por razones de rendimiento, algo más es fundamentalmente erróneo en su aplicación - considerar el uso de alguna otra función de registro o de la interfaz de usuario;)

3

Otra pregunta desbordamiento de pila se dirigió a la velocidad relativa del C-estilo I formateado/O vs. C++ iostreams:

Nótese, sin embargo, que los puntos de referencia tratados fueron para dar formato a los buffers de memoria. Supongo que si realmente está realizando la E/S a una consola o archivo, las diferencias relativas de velocidad serían mucho más pequeñas debido a que la E/S toma más tiempo total.

-3

Debe nunca debe hacer esta pregunta, ya que el usuario solo podrá leer más lento que los dos.

Si necesita una rápida ejecución, no utilice tampoco.

Como han mencionado otros, use algún tipo de registro si necesita un registro de las operaciones.

+3

-1 por suponer que cada aplicación que escribe en su salida está diseñada para estar lista en tiempo real por un usuario. Muchas aplicaciones de servidor se conectan a stdout incluso en contextos sensibles al rendimiento. – Tom

2

Si está utilizando C++, debe usar cout en su lugar, ya que printf pertenece a la familia de funciones C. Se han realizado muchas mejoras para cout de las que puede beneficiarse. En cuanto a la velocidad, no es un problema ya que la E/S de la consola va a ser lenta de todos modos.

2

Para resolver esto:

#include <iostream> 
#include <cstdio> 
#include <ctime> 
using namespace std; 

int main(int argc, char * argcv[]) { 
    const char * const s1 = "some text"; 
    const char * const s2 = "some more text"; 
    int x = 1, y = 2, z = 3; 
    const int BIG = 2000; 
    time_t now = time(0); 
    for (int i = 0; i < BIG; i++) { 
     if (argc == 1) { 
      cout << i << s1 << s2 << x << y << z << "\n"; 
     } 
     else { 
      printf("%d%s%s%d%d%d\n", i, s1, s2, x, y, z); 
     } 
    } 
    cout << (argc == 1 ? "cout " : "printf ") << time(0) - now << endl; 
} 

produce tiempos idénticos para cout y printf.

-2

Evidencia anecdótica:
Una vez diseñé una clase de registro para usar los operadores ostream: la implementación fue terriblemente lenta (para grandes cantidades de datos).

No lo analicé demasiado, por lo que también podría haber sido causado por no usar ostreams correctamente, o simplemente debido a la cantidad de datos registrados en el disco. (La clase ha sido descartada debido a los problemas de rendimiento y en la práctica se prefiere el estilo printf/fmtmsg.)

Estoy de acuerdo con las otras respuestas que en la mayoría de los casos, no importa. Si el resultado realmente es un problema, debe considerar formas de evitarlo/retrasarlo, ya que las actualizaciones de visualización reales suelen costar más que una construcción de cadenas implementada correctamente. Miles de líneas desplazándose en milisegundos no son muy informativas de todos modos.

0

Debajo del capó, ambos usarán el mismo código, por lo que las diferencias de velocidad no importarán.

Si solo está ejecutando en Windows, el cprintf no estándar() puede ser más rápido ya que omite muchas de las cosas de las secuencias.

Sin embargo, es un requisito extraño. Nadie puede leer tan rápido. ¿Por qué no escribir la salida en un archivo, y luego el usuario puede navegar por el archivo cuando lo desee?

1

Hace poco estaba trabajando en una aplicación de consola C++ en Windows que copió archivos usando CopyFileEx y hacía eco de las rutas 'a' y 'de' a la consola para cada copia y luego visualizaba el rendimiento promedio al final de la operación .

Cuando ejecuté la aplicación de la consola usando printf para hacer eco de las cadenas obtenía 4mb/seg, al reemplazar el printf con std :: cout el rendimiento se redujo a 800kb/seg.

Me preguntaba por qué la llamada std :: cout era mucho más cara e incluso llegó a repetir la misma cadena en cada copia para obtener una mejor comparación de las llamadas. Hice varias ejecuciones para igualar la comparación, pero la diferencia de 4x persistió.

Entonces me encontré this respuesta en stackoverflow ..

Encendido de almacenamiento en búfer para la salida estándar resolvieron el problema, ahora mis números de rendimiento para printf y std :: cout son más o menos lo mismo.

No he profundizado en la forma en que printf y cout difieren en el almacenamiento en búfer de la salida de la consola, pero la configuración del búfer de salida antes de comenzar a escribir en la consola resolvió mi problema.

0

¿Por qué no haces un experimento? En promedio para mí, imprimir la cadena helloperson; \ n utilizando printf toma, en promedio, 2 tics de reloj, mientras que usar cout endl toma una gran cantidad de tiempo - 1248996720685 tics de reloj. Usando cout con "\ n" como la nueva línea toma solo 41981 tics de reloj. La URL corta para mi código es el siguiente:

cpp.sh/94qoj

enlace puede haber expirado.

Para responder a su pregunta, printf es más rápido.

#include <iostream> 
#include <string> 
#include <ctime> 
#include <stdio.h> 
using namespace std; 
int main() 
{ 
    clock_t one; 
    clock_t two; 
    clock_t averagePrintf; 
    clock_t averageCout; 
    clock_t averagedumbHybrid; 
    for (int j = 0; j < 100; j++) { 
    one = clock(); 
    for (int d = 0; d < 20; d++) { 
     printf("helloperson;"); 
     printf("\n"); 
    } 
    two = clock(); 
    averagePrintf += two-one; 

    one = clock(); 
    for (int d = 0; d < 20; d++) { 
     cout << "helloperson;"; 
     cout << endl; 
    } 
    two = clock(); 
    averageCout += two-one; 

    one = clock(); 
    for (int d = 0; d < 20; d++) { 
     cout << "helloperson;"; 
     cout << "\n"; 
    } 
    two = clock(); 
    averagedumbHybrid += two-one; 
    } 
    averagePrintf /= 100; 
    averageCout /= 100; 
    averagedumbHybrid /= 100; 
    cout << "printf took " << averagePrintf << endl; 
    cout << "cout took " << averageCout << endl; 
    cout << "hybrid took " << averagedumbHybrid << endl; 
} 

Sí, usé la palabra tonto. Primero lo hice por mí mismo, pensando que los resultados eran una locura, así que lo busqué, y terminé publicando mi código.

creo que sirve, Ndrewffght

+0

Usted plantea un buen punto, algunas cosas son fácilmente comprobables, con solo unas pocas líneas de código. ** Debe copiar el código a esta respuesta ** en caso de que su url expire y otros deseen usarlo. –

+0

mi hipótesis es que endl toma una gran cantidad de tiempo, porque endl imprime una línea nueva y/o retorno de carro, dependiendo de su sistema operativo. Luego, vacía la corriente, consumiendo tiempo. Por cierto, @RegularJoe, publicaré el código – ndrewxie

Cuestiones relacionadas