13

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

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

更新:

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

4

6 回答 6

26

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

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

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

于 2009-01-25T06:20:26.743 回答
4

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

于 2009-01-25T06:11:33.563 回答
3

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

就像 PolyThinker 说的那样,您最好的选择是通过分析器运行您的程序以确定问题出在哪里。

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

于 2009-01-25T07:02:56.080 回答
2

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

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

于 2009-01-25T06:47:27.220 回答
1

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

于 2009-02-01T23:43:44.810 回答
0

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

  1. 你使用缓冲(我不能强调足够)
  2. 您自己操作缓冲区(也就是说,如果您需要链接问题中的 OP 等性能),这与使用FILE*.

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

于 2015-03-07T18:51:34.760 回答