C:为什么fprintf(stdout,....)这么慢?

时间:2012-07-19 10:09:49

标签: c

我仍然经常使用控制台输出来获取我的代码中发生的事情。 我知道这可能有点老式,但我也用它来“管”stdout 到日志文件等。

然而,事实证明,对于某些人来说,控制台的输出速度会变慢 原因。我想知道是否有人可以解释为什么fprintf()到控制台 窗口似乎有点阻塞。

到目前为止我做过/诊断过的事情:

  1. 我把时间测量得很简单 fprintf(stdout,"quick fprintf\n"); 它需要:0.82ms(平均)。由于vsprintf_s(...)在几微秒内将相同的输出写入字符串,因此考虑的时间太长。因此,必须对控制台进行一些特定的阻止。

  2. 为了摆脱阻塞,我使用vsprintf_s(...)将我的输出复制到一个类似于fifo的数据结构中。数据结构受临界区对象的保护。然后,一个单独的线程通过将排队的输出放入控制台来对数据结构进行取消。

  3. 通过引入管道服务我可以获得进一步的改进。 我的程序输出(应该最终在控制台窗口中)按以下方式输出:

    • A vsprintf_s(...)将输出格式化为简单字符串。
    • 字符串排队成一个类似于fifo的数据结构,例如链表结构。此数据结构受关键部分对象保护。
    • 第二个线程通过将输出字符串发送到命名管道来使数据结构出列。
    • 第二个进程读取命名管道并将字符串再次放入一个类似于fifo的数据中 结构体。这是为了使读数远离阻塞输出到控制台。 读取过程快速读取命名管道并持续监视管道缓冲区的填充水平。
    • 第二个进程中的第二个线程最终将fprintf(stdout,...)的数据结构出列到控制台。
  4. 所以我有两个进程,每个进程至少有两个线程,它们之间有一个命名管道,以及管道两侧的fifo数据结构,以避免在管道缓冲区满的情况下阻塞。

    要确保控制台输出是“非阻塞”,这是很多东西。但结果是 还不错。我的主程序可以在几微秒内编写复杂的fprintf(stdout,...)。

    也许我之前应该问过:还有其他(更容易!)的方式来获得非阻塞控制台输出吗?

1 个答案:

答案 0 :(得分:12)

我认为时间问题与控制台默认情况下行缓冲的事实有关。这意味着每次向其写入'\n'字符时,整个输出缓冲区都会被发送到控制台,这是一项相当昂贵的操作。这是您为线路立即显示的价格。

您可以通过将缓冲策略更改为完整缓冲来更改此默认行为。结果是输出将以等于缓冲区大小的块发送到控制台,但单个操作将更快完成。

在您第一次写入控制台之前进行此调用:

char buf[10000];
setvbuf(stdout, buf, _IOFBF, sizeof(buf));

单个写入的时间应该会改善,但输出不会立即出现在控制台中。这对于调试来说不太有用,但时间会有所改善。如果你设置一个按照常规时间间隔调用fflush(stdout)的线程,比如每秒一次,你应该在单个写操作的性能和编写输出的程序之间的延迟和你的时间之间得到合理的平衡。实际上可以在控制台上看到它。