为什么" slurping "文件不是一个好的实践?

14 浏览
0 Comments

为什么" slurping "文件不是一个好的实践?

为什么对于普通的文本文件I/O来说,“吸入”(slurping)文件不是一个好的做法,什么时候会有用呢?

例如,为什么我不应该使用这些方法?

File.read('/path/to/text.txt').lines.each do |line|
  # 处理每一行
end

或者

File.readlines('/path/to/text.txt').each do |line|
  # 处理每一行
end

0
0 Comments

“Slurping”文件为什么不是一种良好的正常文本文件I/O的做法?

在很多情况下,将整个文件读入内存是不可行的(因为要么文件太大,要么字符串操作具有指数O()的空间复杂度)。

通常情况下,你无法预测文件的大小(上述情况的特例)。

你应该始终注意内存使用情况,如果有其他选择(例如逐行读取),将整个文件一次性读入内存(即使在简单情况下)也不是一个好的做法。我从经验中知道,在这方面,VBS很糟糕,人们被迫通过命令行来处理文件。

这个概念不仅适用于文件,还适用于任何内存大小快速增长并且必须逐次处理每个迭代(或行)的其他过程。生成器函数通过逐一处理每个过程或读取的行来帮助您,以避免在内存中处理所有数据。

作为一个额外的说明,Python在读取文件方面非常聪明,它的open()方法默认按行读取。参见“Improve Your Python: 'yield' and Generators Explained”,其中解释了生成器函数的一个很好的用例示例。

我喜欢这句话“它的open()方法默认按行读取。”这是一个更聪明的方式,因为这样默认值就是安全的路径,人们必须明确地要求将文件读入内存。如果他们必须思考后果,他们就不会经常做错误的事情。

因此,"slurping"文件不是一个好的做法,原因如下:

1. 将整个文件读入内存可能导致内存不足或性能问题。

2. 无法预测文件的大小,因此不宜一次性读入内存。

3. 应该始终考虑内存使用情况,如果有其他选项,应该选择逐行读取。

4. 使用生成器函数可以逐行处理数据,避免将全部数据加载到内存中。

解决方法是使用逐行读取的方法,例如Python的open()方法默认按行读取文件。这样的方法更安全,需要明确地要求将文件读入内存。

0
0 Comments

“ slurping”是指一次性读取整个文件的操作,而不是逐行或逐块读取。这个操作的出现是因为程序在处理输入数据之前需要将整个文件读取到内存中,然后再对数据进行处理。这种做法在使用管道时是不可取的,因为管道中的输入文件可能很小但处理速度很慢。如果程序使用“ slurping”操作,那么它就无法在数据可用时立即处理数据,而是必须等待输入完成。这个等待时间可能是任意长的,可能是几个小时、几天,或者更长的时间,特别是当在一个大型层次结构中使用grep或find命令时。另外,输入文件可能是无法完成的,例如“journalctl -f”命令会持续输出系统中发生的事件,“tshark”命令会持续输出网络中的活动,“ping”命令会持续进行ping操作。而/dev/zero是无限的,/dev/urandom是无限的。

唯一可以接受“ slurping”操作的情况可能是在配置文件中,因为在完成读取之前,程序可能无法执行任何操作。

在管道中使用“ slurping”操作很可能会欺骗不知情的用户,因为看起来程序已经挂起了,按下CTRL+C将会终止程序而没有结果。只有当他们使用一个小文件进行测试时,才能看到输出结果,对于大文件,要么会导致代码崩溃,要么会导致处理延迟,因为机器会分配内存。后一种情况是我从中吸取教训的原因。

0
0 Comments

为什么" slurping "文件不是一个好的做法?

"Slurping"是指一次性将整个文件读入内存的操作。虽然对于小文件来说这并不是什么大问题,但是当文件大小超过一定阈值时,这种操作会消耗大量的内存和CPU时间。如果数据消耗的空间太大,操作系统就会介入,将数据写入磁盘,这将导致程序运行变慢甚至崩溃。在需要快速响应的服务器应用程序中,这种操作甚至可能导致整个应用程序瘫痪。

"Slurping"通常是基于对文件I/O速度的误解或者认为将缓冲区读取后再拆分比逐行读取更快的错误观念。

为了解决这个问题,可以考虑使用逐行读取文件的方式,不需要一次性将整个文件读入内存。同时,可以考虑维护一个小缓冲区,存储最后 "n" 行的数据,并进行扫描操作。这样可以避免由于尝试读取和存储整个文件而导致的内存管理问题。在Perl相关的博客 "Perl Slurp-Eaze" 中讨论了这个问题,并提出了使用全文件读取的合理性和应用方法,同样适用于Ruby语言。

此外,不要" slurp "文件还有其他很多理由,可以参考 "How to search file text for a pattern and replace it with a given value"。

虽然这样做可以提高性能,但是读者可能希望知道应该采取哪些替代方法。可以考虑给出一些建议供读者参考。

需要注意的是,在测量文件读取性能时,应该考虑到文件系统缓存的影响。如果文件系统缓存足够大,可以帮助逐行读取方式,从缓存中读取数据而不需要为整个文件分配内存。但是,如果文件大小超过缓存大小,逐行读取方式可能需要额外的读取操作,这可能会影响性能,尽管并不会像超出可用内存并进行分页操作那样严重。

0