【问题标题】:Fastest way to read a pipe from C/C++ program?从 C/C++ 程序中读取管道的最快方法?
【发布时间】:2014-03-23 11:18:34
【问题描述】:

如果我想将字节数据通过管道传输到 Linux 上的 C/C++ 程序,如下所示:

cat my_file | ./my_app

但是:

  1. 我们不能假设管道数据将来自文件
  2. 我们希望将数据解释为文件中的字节(而不是字符串)

从 C/C++ 应用程序中读取管道的最快技术是什么?

我做了一点研究,发现:

  • read()
  • std::cin.read()
  • popen()

但我不确定是否有更好的方法,或者上述哪种方法更好。

编辑:对此有性能要求,因此我要求使用开销最小的技术。

【问题讨论】:

  • 注意popen() 不会从管道中读取任何内容,而只会为您提供可用于调用read() 的必要文件描述符。
  • 不是popen()。在 C 中,使用read();在 C++ 中,可能再次使用 read(),但使用 std::cin 也可以。
  • 你为什么要关心性能?在 shell 中使用 | 并从 std::cin 读取将相当不错,灵活且健壮。
  • 仅供参考,cat my_file | ./my_app./my_app <file 慢,而且灵活性较差(您会得到一个无法打开 seek() 的描述符)。为什么要这样指定?
  • @CharlesDuffy 只是我的误解,有两种方法,一种更快......

标签: c++ linux shell unix pipe


【解决方案1】:

您为什么这么关心性能?

来自/dev/urandom 的 1 GB 可以在 1 分钟内通过管道传输到 wcwc 有 15% 的时间在运行,其余时间等待数据)!试试time (head -1000000000c /dev/urandom|wc)

但最快的方法是使用read(2) 系统调用和一个相当大的缓冲区(例如 64Kbytes 到 256Kbytes)。

当然,阅读Advanced Linux Programming 并仔细阅读syscalls(2) 相关的man 页面。

研究Linux kernelGNU libcmusl-libc的源代码。它们都是open source 项目,因此请随时为它们做出贡献并改进它们。

但我敢打赌,在实践中使用 popenstdin 或从 std::cin 读取不会增加太多开销。

您还可以使用setvbuf(3) 增加stdio 缓冲区。

另见this question

(如果您从 stdin 读取文件描述符为 STDIN_FILENO 即 0)

您可能对time(7)vdso(7)syscalls(2) 感兴趣

您当然应该阅读GCCthis draft 报告的文档。

您可以使用machine learning 技术来优化性能。

查看MILEPOST GCCCtuning 项目。考虑加入RefPerSys 之一。当然阅读Understanding machine learning: From theory to algorithms ISBN 978-1-107-05713-5

【讨论】:

  • 请问,如何获取第二个参数的文件描述符?
  • 对不起最后一个问题-我即将用您建议的系统调用 read() 替换我的 std::cin.read() 。但是,我也有一个 while 循环检查 !std::cin.eof() 以便我抓取所有字节。要查看 read() 系统调用的全部好处,有没有一种方法可以替换对 while(!std::cin.eof()) 的检查?
  • 我不明白你为什么这么关心性能。但请阅读read(2) 的手册页。 您的应用程序是什么?请编辑您的问题以提供更多信息。
  • @user997112,不要混合使用同一个文件描述符的缓冲和非缓冲调用——如果你使用read()(它是非缓冲的),你不应该使用any std::cin 来电。
【解决方案2】:

当您像这样通过管道输入数据时,管道输入标准输入。只需像普通控制台程序一样从 cin(或 stdin)读取。

只需使用std::cin.read()。没有理由与popen() 或类似的东西打交道。


只是为了澄清......没有特定于管道的方式来读取输入。就您的程序而言,有 cin 就是这样。

这个问题可能会帮助您提高速度... Why is reading lines from stdin much slower in C++ than Python?

【讨论】:

  • 在编写时必须考虑到高性能——这就是为什么我要问开销最小的方法是什么?
  • 最小化开销是非常依赖于情境的——有时标准库提供的缓冲会有所帮助,有时会带来伤害。我不知道你能得到一个总是正确的通用答案;你可能会更好地进行基准测试。
  • 除了使用 std::cin::read() 之外,我还需要对哪些其他可能性进行基准测试?
  • 嗯,std::cin::read() 是 C++ 方式。还有 C 标准库调用,以及直接调用您的操作系统系统调用。而且您的操作系统和标准库通常会提供很多用于调优的标志。
  • 但是除非您已经测量到足以知道您有问题,并且您知道导致问题的是读取过程,否则您为什么要从这里开始? :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-30
  • 2012-02-29
相关资源
最近更新 更多