有人告诉我,我的库比它应该慢30倍以上,解析特定文件(文本文件,大小326 KB)的速度太慢。用户建议可能是我使用的是std::ifstream,而不是FILE。
我不想盲目重写,所以我想我应该先检查一下这里,因为我的猜测是瓶颈在其他地方。我正在逐字阅读,所以我使用的功能只有get()、peek()和tellg()/seekg()。
更新:
我分析了一下,然后得到了令人困惑的输出——gprof似乎并没有认为花了这么长时间。我重写了程序,先把整个文件读到一个缓冲区,速度加快了大约100倍。我认为问题可能是tellg()/seekg()花了很长时间,但gprof可能因为某种原因看不到这个问题。在任何情况下,ifstream似乎都不会缓冲整个文件,即使是对于这个大小。
我觉得这没什么区别。特别是如果您正在逐字符地读取数据,那么I/O的开销很可能会完全支配其他任何内容。为什么一次只读取一个字节?你知道它有多低效吗?
在326KB的文件中,最快的解决方案很可能是立即将其读取到内存中。
std::ifstream和c等价物之间的区别,基本上是一个或两个虚拟函数调用。如果每秒执行数千万次,这可能会有所不同,否则就不真实了。文件I/O通常速度很慢,以至于用来访问它的API实际上并不重要。更重要的是读/写模式。很多查找都不好,顺序读/写都很好。
- 实际上,我不知道效率有多低。我只是假设在幕后,它把它读到记忆中。我想我会做的。
- 一些输入流被缓冲。如果代码一次读取一个字符,并不意味着底层流也会这样做。
- 文件和fstream都被缓冲(尽管缓冲区可能太小),Linux对磁盘访问进行了大量优化,因此相对较小的文件将被加载到内存中(Windows也这样做)。
- 取决于它缓冲了多少等等。我敢打赌,一次读取整个文件还是会更快。
- @简单的陈述。可能会更快,但我愿意赌得不算太大。
- 我有种感觉,他是读->过程->写模式,每字符。所有的缓冲策略都会陷入困境。
- 关于流缓冲区:我曾经看过mingw附带的iostream库源。输入流的标准缓冲区大小仅为一个或两个字符,即仅足以允许一个ungetc操作。在(C)POSIX规范中,EDOCX1至少1次的能力也是一个要求;看来C的EDCOX1×3和C++的EDCOX1〔0〕不需要提供更大的缓冲区。
它应该稍微慢一点,但正如您所说,它可能不是瓶颈。你为什么不介绍一下你的程序,看看是不是这样?
我认为不太可能通过从fstream切换到file*来解决您的问题,通常这两者都由C库进行缓冲。操作系统也可以缓存读取(Linux在这方面非常好)。考虑到您正在访问的文件的大小,它很可能完全在RAM中。
就像PolyThinker所说,你最好的选择是通过一个分析器运行你的程序,并确定问题在哪里。
另外,如果您的磁盘严重碎片化,那么使用seekg/tellg可能会导致显著的延迟,因为要第一次读取文件,磁盘必须将磁头移动到正确的位置。
所有的基准都是邪恶的。只需为您期望的数据配置您的代码。
我对Ruby、Python、Perl、C++进行了一次I/O性能比较。对于我的数据、语言版本等,C++的变体要慢几倍(这是当时的一大惊喜)。
- C怎么样?如果C++以外的任何一种语言运行得比C快,我会感到非常惊讶。
- @RR-如果你的磁盘不能提供超过100M/s的数据,那么你的C程序可以处理1g/s并不重要。正如其他答案已经说过的那样,磁盘I/O通常比你程序中的其他任何东西慢得多。有关I/O性能的相关问题:为什么STDIN中的读行比Python慢得多?在C++中同时读取一个完整的文件,第2部分
- 在你的文章中,你说C++在Ruby、Python和其他人中表现最差。这应该与I/O性能无关,这是所有这些语言的统一瓶颈。这就是为什么我会惊讶地发现C的表现比Ruby差,例如,主要是因为Ruby是用C编写的。
- @ RR-:1。如果I/O占主导地位,除非你是谷歌,否则语言无关紧要。2。如果文件已被缓存,请阅读我提供的链接,以查看用同一语言编写的程序如何在同一问题上显示不同的性能结果。
我同意你应该介绍一下。但是,如果您一次读取一个字符的文件,那么创建一个内存映射文件怎么样?这样,您就可以将文件视为一个字符数组,操作系统应该为您处理所有的低级缓冲。最简单、可能也是最快的解决方案是在我的书中获胜。:)
这是一个很好的基准,它表明在极端情况下,fstreams实际上相当慢…除非:
你使用缓冲(我强调不够)
您自己操作缓冲区(也就是说,如果您需要诸如链接问题中的op之类的性能),这与使用FILE*没有什么不同。
不过,你不应该过早优化。fstreams通常更好,如果您需要在路上对它们进行优化,您可以在以后以很低的成本进行优化。为了提前做好最坏情况的准备,我建议现在就为fstream创建一个最小的代理,这样以后您就可以优化它,而无需接触任何其他内容。