perl 中的标量变量有任何限制吗?
Is there any limit for scalar variable in perl?
现在我正在处理大于 (1.5 GB) 的大文件。所以我用了File::Map
。当输入大于 2.1 GB
脚本失败并显示错误 Use of uninitialized value $count in print at file.pl line 16.
.
但是脚本是运行2.1GB and below 2.1GB
我的脚本如下
use warnings;
use strict;
use File::Map 'map_file';
my $filename ="/root/Desktop/test_sequence/human_genome";
map_file (my $map,$filename);
my $count;
$count++ while ($map=~/>/g);
print $count; #The file has only 14 `>` so result is 14.
同时我在没有模块的情况下试了一下。它也以同样的错误终止。
use warnings;
use strict;
my $filename ="/root/Desktop/test_sequence/human_genome";
open my $fh,"<",$filename or die "$!";
my $m = do{local $/; <$fh>};
my $count;
$count++ while ($m=~/>/g);
print $count;
不知道这里有什么问题?
问题确实是最大标量大小。理论上它可以在 32 位 perl 上达到 4 GB,但是由于您的地址 space 被限制为容纳 OS 之类的东西,2-3.5 GB 通常是真正的限制。使用 64 位 OS 和 perl 它应该可以工作。
See this answer一些细节。
编辑:在这里工作正常,Fedora 上的 perl 5.22.2,x86_64-linux-thread-multi:
$ dd if=/dev/zero of=zero bs=1M count=5000
5000+0 records in
5000+0 records out
5242880000 bytes (5.2 GB) copied, 34.8694 s, 150 MB/s
$ perl -e 'sub wat{open my $fh, ">>zero" or die $!;
seek($fh,shift,0); syswrite($fh, ">");}
wat(1000);
wat(100_000_000);
wat(4_500_000_000);'
$ time perl map.pl
3
real 0m5.638s
user 0m3.921s
sys 0m1.717s
您在几个地方之一达到了有符号 32 位整数限制
32 位有符号值允许从 0x1000_0000
到 0x7FFF_FFFF
的值,即 -2,147,483,648 到 2,147,483,647。因此您的 2.1GB 限制
我不知道这是否是您构建的 perl 的限制,或者它是否是 File::Map
的一部分
任何大小的文件都可以通过一次读取一行来非常简单地处理,并且由于您的目的似乎只是计算 Unicode GREATER-THAN SIGN
字符的数量,您可以很容易地做到这一点这个
use strict;
use warnings;
use constant HUMAN_GENOME => '/root/Desktop/test_sequence/human_genome';
my $count = do {
open my $fh, '<', HUMAN_GENOME or die sprintf qq{Unable to open "%s": $!}, HUMAN_GENOME;
my $n = 0;
$n += tr/>// while <$fh>;
$n;
};
print $count;
现在我正在处理大于 (1.5 GB) 的大文件。所以我用了File::Map
。当输入大于 2.1 GB
脚本失败并显示错误 Use of uninitialized value $count in print at file.pl line 16.
.
但是脚本是运行2.1GB and below 2.1GB
我的脚本如下
use warnings;
use strict;
use File::Map 'map_file';
my $filename ="/root/Desktop/test_sequence/human_genome";
map_file (my $map,$filename);
my $count;
$count++ while ($map=~/>/g);
print $count; #The file has only 14 `>` so result is 14.
同时我在没有模块的情况下试了一下。它也以同样的错误终止。
use warnings;
use strict;
my $filename ="/root/Desktop/test_sequence/human_genome";
open my $fh,"<",$filename or die "$!";
my $m = do{local $/; <$fh>};
my $count;
$count++ while ($m=~/>/g);
print $count;
不知道这里有什么问题?
问题确实是最大标量大小。理论上它可以在 32 位 perl 上达到 4 GB,但是由于您的地址 space 被限制为容纳 OS 之类的东西,2-3.5 GB 通常是真正的限制。使用 64 位 OS 和 perl 它应该可以工作。
See this answer一些细节。
编辑:在这里工作正常,Fedora 上的 perl 5.22.2,x86_64-linux-thread-multi:
$ dd if=/dev/zero of=zero bs=1M count=5000
5000+0 records in
5000+0 records out
5242880000 bytes (5.2 GB) copied, 34.8694 s, 150 MB/s
$ perl -e 'sub wat{open my $fh, ">>zero" or die $!;
seek($fh,shift,0); syswrite($fh, ">");}
wat(1000);
wat(100_000_000);
wat(4_500_000_000);'
$ time perl map.pl
3
real 0m5.638s
user 0m3.921s
sys 0m1.717s
您在几个地方之一达到了有符号 32 位整数限制
32 位有符号值允许从 0x1000_0000
到 0x7FFF_FFFF
的值,即 -2,147,483,648 到 2,147,483,647。因此您的 2.1GB 限制
我不知道这是否是您构建的 perl 的限制,或者它是否是 File::Map
任何大小的文件都可以通过一次读取一行来非常简单地处理,并且由于您的目的似乎只是计算 Unicode GREATER-THAN SIGN
字符的数量,您可以很容易地做到这一点这个
use strict;
use warnings;
use constant HUMAN_GENOME => '/root/Desktop/test_sequence/human_genome';
my $count = do {
open my $fh, '<', HUMAN_GENOME or die sprintf qq{Unable to open "%s": $!}, HUMAN_GENOME;
my $n = 0;
$n += tr/>// while <$fh>;
$n;
};
print $count;