我仍然经常使用控制台输出来了解我的代码中发生了什么。我知道这可能有点过时了,但我也用它来将标准输出“管道”到日志文件等中。
但是,事实证明,控制台的输出由于某种原因变慢了。我想知道是否有人可以解释为什么控制台窗口的 fprintf() 似乎有点阻塞。
到目前为止我所做/诊断的事情:
我测量了一个简单的
fprintf(stdout,"quick fprintf\n");
它需要的时间:0.82ms(平均)。这被认为太长了,因为 avsprintf_s(...)
在几微秒内将相同的输出写入字符串。因此,必须有一些专门针对控制台的阻塞。为了摆脱阻塞,我曾经
vsprintf_s(...)
将输出复制到类似 fifo 的数据结构中。数据结构受临界区对象保护。然后,一个单独的线程通过将排队的输出放到控制台来取消数据结构的排队。通过引入管道服务,我可以获得进一步的改进。我的程序的输出(应该在控制台窗口中结束)按照以下方式进行:
- A
vsprintf_s(...)
将输出格式化为简单的字符串。 - 字符串被排队到类似fifo的数据结构中,例如链表结构。此数据结构受临界区对象的保护。
- 第二个线程通过将输出字符串发送到命名管道来使数据结构出队。
- 第二个进程读取命名管道并将字符串再次放入类似 fifo 的数据结构中。这是使读数远离控制台的阻塞输出所必需的。读取过程在读取命名管道时速度很快,并持续监控管道缓冲区的填充水平。
- 第二个进程中的第二个线程最终将数据结构出列
fprintf(stdout,...)
到控制台。
- A
所以我有两个进程,每个进程至少有两个线程,它们之间有一个命名管道,管道两侧都有类似 fifo 的数据结构,以避免在管道缓冲区已满时阻塞。
要确保控制台输出是“非阻塞”的,就需要做很多事情。但结果还不错。我的主程序可以在几微秒内编写复杂的 fprintf(stdout,...)。
也许我应该早点问:有没有其他(更简单!)的方式来获得非阻塞控制台输出?