【问题标题】:Is std::ifstream significantly slower than FILE?std::ifstream 是否比 FILE 慢得多?
【发布时间】:2010-10-03 09:30:55
【问题描述】:

我被告知我的库比应有的速度慢,解析特定文件(文本文件,大小 326 kb)的速度要慢 30 倍以上。用户建议可能是我用的是std::ifstream(大概不是FILE)。

我不想盲目地重写,所以我想我先在这里检查一下,因为我的猜测是瓶颈在其他地方。我正在逐字阅读,所以我使用的唯一函数是get()peek()tellg()/seekg()

更新:

我进行了分析,并得到了confusing 输出 - gprof 似乎并不认为它花了这么长时间。我重写了程序,首先将整个文件读入缓冲区,它的速度提高了大约 100 倍。我认为问题可能是 tellg()/seekg() 花了很长时间,但 gprof 可能由于某种原因无法看到。在任何情况下,ifstream 似乎没有缓冲整个文件,即使对于这个大小。

【问题讨论】:

标签: c++ optimization file-io ifstream


【解决方案1】:

Here 是一个出色的基准,它表明在极端条件下,fstreams 实际上非常慢......除非:

  1. 您使用缓冲(我怎么强调都不为过)
  2. 您自己操作缓冲区(即,如果您需要链接问题中的 OP 等性能),这与使用 FILE* 没有太大区别。

不过,您不应该过早地进行优化。 fstreams 通常更好,如果您需要在以后优化它们,您可以稍后再做,而且成本很低。为了提前做好最坏的准备,我建议现在为fstream 创建一个最小代理,以便您以后可以对其进行优化,而无需触及任何其他内容。

【讨论】:

    【解决方案2】:

    我认为您的问题不太可能通过从 fstream 切换到 FILE* 来解决,通常两者都由 C 库缓冲。操作系统也可以缓存读取(Linux 在这方面非常好)。鉴于您正在访问的文件的大小很可能它会完全在 RAM 中。

    就像 PolyThinker 所说,最好的办法是通过分析器运行程序以确定问题出在哪里。

    此外,如果您的磁盘碎片严重,这可能会导致明显的延迟,因为第一次读取文件时磁盘必须将磁头移动到正确的位置。

    【讨论】:

      【解决方案3】:

      我同意你应该配置文件。但是,如果您一次读取一个字符的文件,那么创建一个内存映射文件怎么样?这样,您可以将文件视为字符数组,并且操作系统应该为您处理所有低级缓冲。最简单且可能最快的解决方案是我书中的胜利。 :)

      【讨论】:

        【解决方案4】:

        所有基准都是邪恶的。只需针对您期望的数据分析您的代码即可。

        我在 Ruby、Python、Perl、C++ 之间进行了一次 I/O 性能比较。对于我的数据、语言版本等,C++ 的变体慢了好几倍(当时这是一个很大的惊喜)。

        【讨论】:

        • C 呢?如果除 C++ 之外的任何上述语言的运行速度都比 C 快,我会感到非常惊讶。
        • @rr- 如果你的磁盘不能以超过 100M/s 的速度提供数据,那么你的 C 程序可以处理 1G/s 也没关系。正如其他答案已经说过的那样,磁盘 i/o 通常比程序中的其他任何东西都要慢得多。请参阅有关 I/O 性能的相关问题:Why is reading lines from stdin much slower in C++ than Python?Reading in an entire file at once in C++, part 2
        • 在您的帖子中,您说 C++ 在 Ruby、Python 等中表现最差。这应该与 I/O 性能无关,这对于所有这些语言来说都是一个瓶颈。例如,我会惊讶地发现 C 的行为比 Ruby 差,主要是因为 Ruby 是用 C 编写的。
        • @rr-:1。如果 I/O 占主导地位;除非您是 Google,否则语言无关紧要。 2. 如果文件被缓存,请阅读我提供的链接,看看用相同语言编写的程序如何针对相同问题显示不同的性能结果
        【解决方案5】:

        我认为这不会有什么不同。尤其是当您逐个字符地读取时,I/O 的开销可能会完全支配任何东西。 为什么一次读取单个字节?你知道它的效率有多低吗?

        对于 326kb 的文件,最快的解决方案很可能是一次将其读入内存。

        std::ifstream 和 C 等效项之间的区别基本上是一个或两个虚函数调用。如果每秒执行几千万次,可能会有所不同,否则,就不是真的。文件 I/O 通常很慢,以至于用于访问它的 API 并不重要。更重要的是读/写模式。很多查找都是不好的,顺序读/写是好的。

        【讨论】:

        • 其实我也不知道效率有多低。我只是假设在幕后,它将它读入内存。我想我会这样做。
        • 一些输入流被缓冲。如果您的代码一次读取一个字符,并不意味着底层流也会这样做。
        • FILE 和 fstream 都是缓冲的(虽然缓冲可能太小了),linux 对磁盘访问做了很大的优化,所以你比较小的文件会被加载到内存中(windows 也是这样做的)。跨度>
        • 取决于它的缓冲量等等。我敢打赌,一次读取整个文件仍然会更快。
        • @jalf:声明简单。它可能会更快,但我愿意赌得不大。
        【解决方案6】:

        应该会慢一些,但就像你说的,它可能不是瓶颈。你为什么不分析你的程序,看看是不是这样?

        【讨论】:

          猜你喜欢
          • 2010-09-17
          • 1970-01-01
          • 2012-10-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-10-07
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多