Sigo utilizando la salida de la consola para obtener ideas de lo que ocurre en mi código. Sé que esto puede ser un poco antiguo, pero también lo uso para “canalizar” la salida estándar a los archivos de registro, etc.
Sin embargo, resulta que la salida a la consola se ralentiza por alguna razón. Me preguntaba si alguien podría explicar por qué un fprintf () en una ventana de consola parece estar bloqueando.
Lo que he hecho / diagnosticado hasta ahora:
fprintf(stdout,"quick fprintf\n");
la hora en que un fprintf(stdout,"quick fprintf\n");
simple fprintf(stdout,"quick fprintf\n");
Necesita: 0.82ms (en promedio). Esto se considera demasiado largo ya que un vsprintf_s(...)
escribe la misma salida en una cadena en tan solo unos pocos microsegundos. Por lo tanto, debe haber algún locking específicamente a la consola.
Para evitar el locking, he usado vsprintf_s(...)
para copiar mi salida en una estructura de datos similar a quince. La estructura de datos está protegida por un objeto de sección crítica. A continuación, un subproceso separado está ejecutando la estructura de datos colocando la salida en cola en la consola.
Otra mejora que pude obtener con la introducción de servicios de tuberías. La salida de mi progtwig (que se supone que termina en una ventana de consola) es la siguiente:
vsprintf_s(...)
formatea la salida a cadenas simples. fprintf(stdout,...)
a la consola. Así que tengo dos procesos con al menos dos subprocesos cada uno, una tubería con nombre entre ellos y quince estructuras de datos similares en ambos lados de la tubería para evitar el locking en el caso de que el buffer de tubería esté lleno.
Eso es un montón de cosas para asegurarse de que la salida de la consola sea “sin locking”. Pero el resultado no es tan malo. Mi progtwig principal puede escribir fprintf complejo (stdout, …) en unos pocos microsegundos.
Tal vez debería haber preguntado antes: ¿Hay alguna otra forma (más fácil) de tener una salida de consola sin locking?
Creo que el problema de la sincronización tiene que ver con el hecho de que la consola tiene un búfer de línea por defecto. Esto significa que cada vez que escribe un carácter '\n'
en él, todo el búfer de salida se envía a la consola, lo que es una operación bastante costosa. Este es el precio que paga por que la línea aparezca en la salida inmediatamente.
Puede cambiar este comportamiento predeterminado cambiando la estrategia de almacenamiento en búfer al almacenamiento en búfer completo . La consecuencia es que la salida se enviará a la consola en fragmentos que son iguales al tamaño de su búfer, pero las operaciones individuales se completarán más rápido.
Haga esta llamada antes de escribir por primera vez en la consola:
char buf[10000]; setvbuf(stdout, buf, _IOFBF, sizeof(buf));
El tiempo de las escrituras individuales debería mejorar, pero la salida no aparecerá en la consola inmediatamente. Esto no es demasiado útil para la depuración, pero el tiempo mejorará. Si configura un subproceso que llama a fflush(stdout)
en intervalos de tiempo regulares, por ejemplo, una vez por segundo, debe obtener un equilibrio razonable entre el rendimiento de las escrituras individuales y el retraso entre el progtwig que escribe la salida y el momento en que puede En realidad lo veo en la consola.