Cha*_*hap 6 perl split fileslurp
我有一个要在Perl中处理的多GB文件.逐行读取文件需要几分钟; 通过File :: Slurp将其读入标量需要几秒钟.好.现在,处理标量的每个"线"的最有效方法是什么?我想我应该避免修改标量,例如在处理它时切断每个连续的行,以避免重新分配标量.
我试过这个:
use File::Slurp;
my $file_ref = read_file( '/tmp/tom_timings/tom_timings_15998', scalar_ref => 1 ) ;
for my $line (split /\n/, $$file_ref) {
# process line
}
Run Code Online (Sandbox Code Playgroud)
这是分钟:足够但不是很好.有更快的方法吗?(我的记忆比上帝多.)
split
应该非常快,除非你开始交换.我能看到加速它的唯一方法是编写一个寻找LF而不是使用正则表达式的XS函数.
顺便说一下,你可以通过切换来节省大量内存
while ($$file_ref =~ /\G([^\n]*\n|[^\n]+)/g) {
my $line = $1;
# process line
}
Run Code Online (Sandbox Code Playgroud)
说XS功能.如果您不想选择newSVpvn_flags
,请在if
语句后移动该行.
SV* next_line(SV* buf_sv) {
STRLEN buf_len;
const char* buf = SvPV_force(buf_sv, buf_len);
char* next_line_ptr;
char* buf_end;
SV* rv;
if (!buf_len)
return &PL_sv_undef;
next_line_ptr = buf;
buf_end = buf + buf_len;
while (next_line_ptr != buf_end && *next_line_ptr != '\n')
++next_line_ptr;
rv = newSVpvn_flags(buf, next_line_ptr-buf, SvUTF8(buf_sv) ? SVf_UTF8 : 0);
if (next_line_ptr != buf_end)
++next_line_ptr;
sv_chop(buf_sv, next_line_ptr);
return rv; /* Typemap will mortalize */
}
Run Code Online (Sandbox Code Playgroud)
测试手段:
use strict;
use warnings;
use Inline C => <<'__EOC__';
SV* next_line(SV* buf_sv) {
...
}
__EOC__
my $s = <<'__EOI__';
foo
bar
baz
__EOI__
while (defined($_ = next_line($s))) {
print "<$_>\n";
}
Run Code Online (Sandbox Code Playgroud)