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

标签 c

我仍然经常使用控制台输出来了解我的代码中发生了什么。 我知道这可能有点过时,但我也用它来“管道”标准输出 进入日志文件等。

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

到目前为止我所做/诊断的内容:

  1. 我测量了一个简单的时间 fprintf(stdout,"快速 fprintf\n"); 它需要:0.82ms(平均)。这被认为太久了,因为 vsprintf_s(...) 在短短几微秒内将相同的输出写入字符串。因此,必须有一些专门针对控制台的阻塞。

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

  3. 我可以通过引入管道服务获得进一步的改进。 我的程序的输出(应该在控制台窗口中结束)如下所示:

    • vsprintf_s(...) 将输出格式化为简单的字符串。
    • 字符串被排入类似 fifo 的数据结构中,例如链表结构。此数据结构受临界区对象保护。
    • 第二个线程通过将输出字符串发送到命名管道来使数据结构出队。
    • 第二个进程读取命名管道并将字符串再次放入类似数据的 fifo 中 结构体。这是为了让读数远离控制台的阻塞输出。 读取过程在读取命名管道时速度很快,并连续监视管道缓冲区的填充水平。
    • 第二个进程中的第二个线程最终通过 fprintf(stdout,...) 将数据结构出列到控制台。

所以我有两个进程,每个进程至少有两个线程,它们之间有一个命名管道,管道两边都有类似 fifo 的数据结构,以避免在管道缓冲区已满时阻塞。

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

也许我应该早点问:有没有其他(更简单!)的方法来获得非阻塞控制台输出?

最佳答案

我认为计时问题与默认情况下 行缓冲 控制台有关。这意味着每次您向其写入一个 '\n' 字符时,您的整个输出缓冲区都会发送到控制台,这是一个相当昂贵的操作。这是您为使该行立即出现在输出中而付出的代价。

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

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

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

个别写入的时间应该有所改善,但输出不会立即出现在控制台中。这对调试用处不大,但时序会有所改善。如果您设置了一个定期调用 fflush(stdout) 的线程,比如说,每秒一次,您应该在单个写入的性能和程序写入之间的延迟之间取得合理的平衡输出以及您实际可以在控制台上看到它的时间。

关于C: 为什么 fprintf(stdout,....) 这么慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11558540/

相关文章:

C - 缓冲区溢出问题

有人可以检查我这个初学者 C 程序的算法吗?

c中将一个文件复制到另一个错误

c - wait(status)、WEXITSTATUS(status) 始终返回 0

c - 为什么 double 变量在 c 中除法后不显示余数?

c - 为什么 strcat 实现不会导致段错误?

c - 如何在 OSX 上制作 .so 可执行文件?

C - 打印没有标准库的参数

c++ - 在 C 中初始化一个 char 数组。哪种方式更好?

c - 在 C 函数中传递和更改数组内部