据我所知,Java和Perl在读取文件时都很难找到一个适合所有默认缓冲区大小的内容,但是我发现他们的选择越来越过时,并且在更改默认选择时遇到问题Perl的.
在Perl的情况下,我认为默认情况下使用8K缓冲区,类似于Java的选择,我找不到使用perldoc网站搜索引擎(真的是Google)关于如何增加默认文件输入缓冲区大小的引用, 64K.
从上面的链接,以显示8K缓冲区如何不缩放:
如果行通常每个大约有60个字符,则10,000行文件中包含大约610,000个字符.通过缓冲逐行读取文件只需要75次系统调用和75次等待磁盘,而不是10,001.
因此,对于每行60个字符(包括末尾的换行符)的50,000,000行文件,使用8K缓冲区,它将进行366211次系统调用以读取2.8GiB文件.顺便说一句,您可以通过在任务管理器进程列表中查看磁盘i/o读取增量(在Windows中至少,*nix中显示同样的东西,我确定)作为您的Perl程序来确认此行为在文本文件中读取需要10分钟:)
有人问起增加了对perlmonks Perl的输入缓冲区大小的问题,有人说在这里,你可以增加"$ /"的尺寸,从而增加缓冲区的大小,但是从的perldoc:
将$ /设置为对整数的引用,包含整数的标量或可转换为整数的标量将尝试读取记录而不是行,最大记录大小为引用的整数.
所以我假设这实际上没有增加Perl在使用典型时从磁盘读取的缓冲区大小:
while(<>) {
#do something with $_ here
...
}
Run Code Online (Sandbox Code Playgroud)
"逐行"成语.
现在它可能是一个不同的"一次读取一条记录,然后将其解析为行",上述代码的版本通常会更快,并绕过标准习惯用语的基础问题而无法更改默认缓冲区大小(如果确实不可能),因为您可以将"记录大小"设置为您想要的任何内容,然后将每条记录解析为单独的行,并希望 Perl做正确的事情并最终为每条记录执行一次系统调用,但它增加了复杂性,而我真正想做的就是通过将上面示例中使用的缓冲区增加到相当大的大小(例如64K),甚至将缓冲区大小调整为使用测试进行长读取的最佳大小来获得轻松的性能提升我的系统上的脚本,无需额外的麻烦.
对于增加缓冲区大小的直接支持,Java中的情况要好得多.
在Java中,我相信java.io.BufferedReader使用的当前默认缓冲区大小也是8192字节,尽管JDK文档中的最新引用是模棱两可的,例如,1.5文档仅说:
可以指定缓冲区大小,或者可以接受默认大小.对于大多数用途,默认值足够大.
幸运的是,您不必信任JDK开发人员为您的应用程序做出正确的决定,并且可以设置您自己的缓冲区大小(在此示例中为64K):
import java.io.BufferedReader;
[...]
reader = new BufferedReader(new InputStreamReader(fileInputStream, "UTF-8"), 65536);
[...]
while (true) {
String line = reader.readLine();
if (line == null) {
break;
}
/* do something with the line here */
foo(line);
}
Run Code Online (Sandbox Code Playgroud)
即使使用巨大的缓冲区和现代硬件,你也可以挤出一次解析一行的性能,而且我确信有很多方法可以通过阅读大文件来读取文件中的每一个性能多行记录并将每个记录分解为令牌,然后每个记录执行一次这些令牌,但是它们增加了复杂性和边缘情况(尽管如果在纯Java中有一个优雅的解决方案(仅使用JDK 1.5中提供的功能)那将是很酷的了解).增加Perl中的缓冲区大小至少可以解决Perl 80%的性能问题,同时保持直接的性能.
我的问题是:
有没有办法在Perl中为上述典型的"逐行"习惯调整缓冲区大小,类似于Java示例中缓冲区大小的增加?