我知道 Java 和 Perl 在读取文件时都非常努力地尝试找到一个适合所有默认缓冲区大小的统一尺寸,但我发现他们的选择越来越过时,并且在更改默认选择时遇到问题它涉及到 Perl。
对于 Perl,我相信它使用 8K默认缓冲区,类似于 Java 的选择,我无法使用 perldoc 网站搜索引擎(真正的 Google)找到关于如何增加默认文件输入缓冲区大小的引用,比如 64K。
从上面的链接中,显示 8K 缓冲区如何无法缩放:
If lines typically have about 60 characters each, then the 10,000-line file has about 610,000 characters in it. Reading the file line-by-line with buffering only requires 75 system calls and 75 waits for the disk, instead of 10,001.
因此对于一个 50,000,000 行的文件,每行 60 个字符(包括末尾的换行符),使用 8K 缓冲区,它将进行 366211 次系统调用来读取一个 2.8GiB 的文件。顺便说一句,您可以通过查看任务管理器进程列表中的磁盘 i/o 读取增量(至少在 Windows 中,*nix 中的顶部也以某种方式显示相同的东西我敢肯定)来确认此行为作为您的 Perl 程序读取一个文本文件需要 10 分钟 :)
有人问过关于在 perlmonks 上增加 Perl 输入缓冲区大小的问题,有人回答了 here您可以增加“$/”的大小,从而增加缓冲区大小,但是来自 perldoc:
Setting $/ to a reference to an integer, scalar containing an integer, or scalar that's convertible to an integer will attempt to read records instead of lines, with the maximum record size being the referenced integer.
所以我假设这实际上并没有增加 Perl 在使用典型时用于从磁盘提前读取的缓冲区大小:
while(<>) {
#do something with $_ here
...
}
“逐行”成语。
现在可能是上述代码的不同“一次读取一条记录,然后将其解析成行”版本通常会更快,并且绕过标准习语的潜在问题并且无法更改默认缓冲区大小(如果这确实不可能),因为您可以将“记录大小”设置为您想要的任何值,然后将每条记录解析为单独的行,希望Perl 做正确的事情并结束每个记录执行一个系统调用,但它增加了复杂性,而我真正想做的是通过将上面示例中使用的缓冲区增加到相当大的大小(比如 64K),甚至调整缓冲区大小来轻松提高性能在我的系统上使用测试脚本将长读的大小调整到最佳大小,而无需额外的麻烦。
就对增加缓冲区大小的直接支持而言,Java 中的情况要好得多。
在 Java 中,我相信 java.io.BufferedReader 使用的当前默认缓冲区大小也是 8192 字节,尽管 JDK 文档中的最新引用是模棱两可的,例如,1.5 文档只说:
The buffer size may be specified, or the default size may be accepted. The default is large enough for most purposes.
幸运的是,使用 Java,您不必相信 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);
}
即使使用巨大的缓冲区和现代硬件,一次解析一行也只能获得这么多的性能,而且我相信有一些方法可以从读取文件中获得每一盎司的性能通过读取大的多行记录并将每条记录分解为标记,然后每条记录对这些标记进行一次操作,但它们增加了复杂性和边缘情况(尽管如果在纯 Java 中有一个优雅的解决方案(仅使用 JDK 1.5 中存在的功能)知道会很酷)。增加 Perl 中的缓冲区大小至少可以解决 Perl 80% 的性能问题,同时保持直截了当。
我的问题是:
对于上述典型的“逐行”习惯用法,是否有一种方法可以在 Perl 中调整缓冲区大小,类似于 Java 示例中缓冲区大小的增加方式?
最佳答案
如果您在支持 setvbuf 的操作系统上运行,您可能会影响缓冲;查看documentation for IO::Handle .
如果您使用的是 perl v5.10 或更高版本,则无需
显式创建一个 IO::Handle 对象,如文档中所述,因为自该版本以来,所有文件句柄都被隐式地祝福到 IO::Handle 对象中。
use 5.010;
use strict;
use warnings;
use autodie;
use IO::Handle '_IOLBF';
open my $handle, '<:utf8', 'foo';
my $buffer;
$handle->setvbuf($buffer, _IOLBF, 0x10000);
while ( my $line = <$handle> ) {
...
}
关于java - 如何在 Perl 中设置文件读取缓冲区大小以针对大文件对其进行优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1251062/
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende