【问题标题】:Is there any limit for scalar variable in perl?perl中的标量变量有限制吗?
【发布时间】:2016-08-03 09:46:43
【问题描述】:

现在我正在处理大于 (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;

不知道这里有什么问题?

【问题讨论】:

  • 如果您所做的只是计算&gt; - 您真的需要将整个文件读入内存吗?
  • @Sobrique 我正在尝试在文件中查找重复项。所以我想计算文件中的标题。那我继续。
  • 你确定没有事先得到Use of uninitialized value $map in pattern match (m//)Use of uninitialized value $m in pattern match (m//)
  • @Borodin,您可能想阅读 OP 的代码。不,这不是我的问题,OP 的代码在这里可以正常工作。我正在尝试找出他的设置中还有什么问题。
  • @Borodin,主题是“我不知道这里有什么问题?”。那么告诉我,这里允许的调查方向是什么?这不是 OP 的代码,也不是 File::Map。我已经验证过了。它在这里按预期工作。你有吗?

标签: perl mmap


【解决方案1】:

问题确实是最大标量大小。理论上它可以在 32 位 perl 上达到 4 GB,但由于您的地址空间被限制以容纳诸如操作系统之类的东西,所以 2-3.5 GB 通常是真正的限制。使用 64 位操作系统和 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

【讨论】:

  • 我正在使用 64 位 centOS 7、32 GB 内存。好的,File::Map 呢?据我了解,它创建了与文件的直接链接。那为什么这也行不通呢?
  • perl -v 说什么?
  • @Sobrique 它显示This is perl 5, version 16, subversion 3 (v5.16.3) built for x86_64-linux-thread-multi (with 29 registered patches, ..
  • @mkHun:接下来的几行将具有use64bitint 的值。可能是undef
【解决方案2】:

您已在多个位置之一达到有符号 32 位整数限制

32 位有符号值允许从 0x1000_00000x7FFF_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;

【讨论】:

  • 我是这么想的,但从他的 perl 版本看来,这听起来不太可能。而File::Map 绝对可以处理 >4 GB,所以它真的有点神秘。当然,运行缓慢的版本比快速损坏的版本要好,但感谢File::Map,在 5.6 秒内通过 5 GB 的速度足够性感,可以继续尝试;)
  • 好吧,我会咬“这听起来不太可能”。为什么?影响你判断的 Perl 代码是什么?
  • “而File::Map 绝对可以处理 >4 GB” 如果您有证据,请出示您的代码以便验证。
  • OP:“我正在使用 64 位 centOS 7”。我没有要检查的 CentOS 7,但我不认为(因此“不太可能”)它们会在 x86_64 上包含 32 位 perl。我证明File::Map 可以处理> 4GB 的证据是OP 的第一个脚本正确计算了我机器上5 GB 文件中的&gt; 字符,最后一个超过4 GB 阈值。除了已经展示的代码之外,我没有使用任何其他代码,当然还有 OP。
猜你喜欢
  • 2021-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-04
  • 1970-01-01
  • 1970-01-01
  • 2010-09-21
  • 1970-01-01
相关资源
最近更新 更多