逐行读取文件与整个文件读取时的性能表现比较

12

一行一行地阅读文件和整个文件一次性读取有没有明显的区别(在理论上)?

一次性读取整个文件确实会对内存使用量产生负面影响,但它会更快吗?

我需要读取一个文件并处理每一行。 我不知道是应该一次读取一行并处理它,还是读取整个文件,全部处理完后再写入输出。

我已经设置了程序逐行读取,并想知道是否值得努力将其更改为读取整个文件(考虑到我的设置,这不容易)。

谢谢,


1
理论上,在逐行程序中,驱动器可能需要更频繁地寻找和读取,这取决于其他正在发生的事情。实际上,这可能不是一个问题,因为缓冲文件I/O可能正在用于读取较大的块。您的里程将根据硬件和算法的细节而异。在优化时,您必须期望编写多个程序迭代,并添加计时器代码或使用分析器来查找最耗时的部分。 - holtavolt
6个回答

3
我认为这要取决于你的应用程序的需求(像大多数事情一样)。就单纯的文件读取而言,在Node.js中使用fs.readFile()比使用可读流或行读取器快大约3-4倍。如果文件非常大并且您正在即时处理输入,则流可能会提供一些额外的性能。如果您的应用程序已经消耗了大量内存,那么流也可能是理想的选择,因为64位系统上的Node进程有大约1.5GB的内存限制。如果数据源相对于CPU的处理速度很慢(如硬盘或磁带上的归档文件、像TCP这样的网络连接),那么按块来处理可能更具有性能。至于将文件读取到内存中与流式传输到内存中的区别,我猜测发出数据事件的函数调用开销以及切换到处理函数回调会减缓整个过程。

3

读取整个文件的速度会稍微快一些,但并不是很快!

但要小心,读取整个文件不具有可扩展性,因为您受到系统中可用内存的限制。一旦文件大小超过程序可用RAM的大小,它将开始使用交换空间,这将使速度变慢。如果文件大小超过虚拟内存可用的大小,则程序将崩溃。


2
像其他人一样,我认为进行更大的读取操作会在一定程度上提高应用程序的性能,但不要期望奇迹。I/O已经在操作系统层面上进行了缓冲,所以您只需要通过减少太多的读取调用来降低开销。一次性读取整个文件是危险的,除非您知道输入文件的最大可能大小。最合理的方法是分块读取文件。
如果您想进一步改善性能,您应该考虑将I/O与处理重叠。假设您按128MB的块读取输入文件。在主线程上,您读取第一个128MB块,然后将其传递给工作线程进行处理。当工作线程开始工作时,主线程会读取第二个128MB块。从那时起,在工作线程处理块N时,主线程正在从磁盘中读取块N+1。

1

将整个文件读入内存通常不是一个好主意,因为文件可能非常大,可能会占用大量内存,并在最坏的情况下耗尽内存。因此,为了平衡性能和内存使用率,您可以将文件的一块读入缓冲区并解析缓冲区。当您完成处理该块时,请读取下一块,直到EOF。

根据您想要实现的目标,需要确定一个良好的块大小。


1
文件系统将为您完成所有这些“块”操作!这被称为缓冲区管理,如果在操作系统缓冲区之上实现自己的缓冲区,只会减慢速度。 - James Anderson
@James Anderson - 你说得对 :) 我将它设置为独占的,因为原帖中提到了“理论上”。 - srikanta

0
说实话,在我的学位期间研究了一段时间的效率后,我得出了这样的结论:这取决于这个文件将被读取的频率。如果只读取一次,那么就全部读取,因为这样可以释放进程以执行其他任务。 还有一件事需要记住,这个文件是否会在以后被编辑并需要更新(例如仅读取更新部分)?如果是这样,您可能需要设置一个标记来识别从哪里读取(然后再次确定更新频率)。但是,如果这是一项一次性工作,请继续整体读取,只要您不需要创建某些文字的标记。 希望这可以帮助到您。

在现代的*nix或Windows操作系统中,这种关于缓冲、进程间共享以及标记更新的工作都由操作系统自动完成。 - James Anderson
我同意......有时候人们过于追求效率,实际上会让情况变得更糟!这是通过实施/干扰缓冲、进程间共享、标记更新等方式实现的。 - sys_debug

0

一个因素是你将要读取多少数据,以及程序最初运行的时间有多长,即是否有任何在性能方面工作的好处。

请参阅this answer中的书籍引用,了解一些关于思考软件性能的好的、通用的建议。

(我知道你是为了一个理论答案,但是当你有限的时间需要花费时,关注性能的这个方面也很重要。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接