此示例脚本:
#!/usr/bin/perl -w
while (1)
{
sleep(1);
}
需要大约264 kB
grep -A1 heap /proc/9216/smaps
0817b000-081bd000 rw-p 0817b000 00:00 0 [heap]
Size: 264 kB
但是当我只添加我的模块时:
#!/usr/bin/perl -w
use my_module;
while (1)
{
sleep(1);
}
需要18092 kB!
grep -A1 heap /proc/9219maps
0817b000-09326000 rw-p 0817b000 00:00 0 [heap]
Size: 18092 kB
注意:'my_module'有很多'use module;'在里面。
如何找到需要这么多内存的内容?
我该如何减少它? (使用'使用模块(功能)'?)
感谢您的帮助。
答案 0 :(得分:14)
插入BEGIN {}
块以缩小罪魁祸首,如
#! /usr/bin/perl
sub grep_heap { print @_, "\n"; system "grep -A1 heap /proc/$$/smaps" }
BEGIN { grep_heap "<null>" }
use warnings;
BEGIN { grep_heap "+warnings" }
use strict;
BEGIN { grep_heap "+strict" }
use Data::Dumper;
BEGIN { grep_heap "+Data::Dumper" }
use POSIX;
BEGIN { grep_heap "+POSIX" }
print "Hi\n";
在我的Linux主机上,我看到了
$ ./prog.pl <null> 0889b000-088de000 rw-p 0889b000 00:00 0 [heap] Size: 268 kB +warnings 0889b000-08920000 rw-p 0889b000 00:00 0 [heap] Size: 532 kB +strict 0889b000-08920000 rw-p 0889b000 00:00 0 [heap] Size: 532 kB +Data::Dumper 0889b000-089a4000 rw-p 0889b000 00:00 0 [heap] Size: 1060 kB +POSIX 0889b000-08ace000 rw-p 0889b000 00:00 0 [heap] Size: 2252 kB Hi
至于如何处理,您可以使用按比例缩小的功能实现替换模块,或者问自己是否真的需要特定的模块。但是,一般来说,perl的设计更倾向于将内存存在于问题中,而现在机器通常会有多个主存储器的gibibytes。
此资源问题是否会导致性能问题?
下面是一个程序,它读取perlmodlib.pod
中的模块列表,并为每个模块将子项分配给require
和import
并检查它自己的堆。
#! /usr/bin/perl
sub heap {
my($heap) = @_;
unless ($heap =~ /^([0-9a-f]+)-([0-9a-f]+)/m) {
warn "$0: unexpected heap:\n$heap";
return -1;
}
hex($2) - hex($1);
}
sub size {
my($bytes) = @_;
my @units = (
[ MiB => "%.1f", 1_024 * 1_024 ],
[ KiB => "%.1f", 1_024 ],
);
for (@units) {
my($unit,$fmt,$n) = @$_;
return sprintf "$fmt %s" => $bytes/$n, $unit
if $bytes >= $n;
}
return "$bytes byte" . ($bytes == 1 ? "" : "s");
}
my %incr;
my $perlmodlib = `perldoc -l perlmodlib`;
die "$0: perldoc failed" unless defined $perlmodlib;
my $base = heap `grep heap /proc/$$/smaps`;
warn "$0: base=" . size($base) . "\n";
chomp $perlmodlib;
open my $fh, "<", $perlmodlib or die "$0: open $perlmodlib: $!";
while (<$fh>) {
next unless /^=head2 Pragmatic Modules/ ..
/^=head2 Extension Modules/;
if (/^=item (\w+(::\w+)*)/) {
my $mod = $1;
(my $path = "$mod.pm") =~ s!::!/!g;
my $pid = open my $fh, "-|";
die "$0: fork: $!" unless defined $pid;
if ($pid == 0) {
open STDERR, ">", "/dev/null" or warn "$0: open: $!";
exec "perl", "-e", <<EOProgram;
BEGIN {
require \"$path\";
eval { $mod->import };
system qq(grep heap /proc/\$\$/smaps);
}
EOProgram
die "$0: exec: $!";
}
else {
local $/;
my $heap = <$fh>;
unless (defined $heap && length $heap) {
warn "$0: use $mod failed";
next;
}
$heap = heap $heap;
$incr{$mod} = $heap > 0 ? $heap-$base : $heap;
}
}
}
foreach my $mod (sort { $incr{$b} <=> $incr{$a} } keys %incr) {
print "$mod - ", size($incr{$mod}), "\n";
}
perl-5.8.8的前几名罪犯:
CPAN::Nox - 9.7 MiB CPAN - 9.6 MiB ExtUtils::MM_VMS - 5.3 MiB CPAN::FirstTime - 5.2 MiB ExtUtils::Installed - 5.2 MiB B::CC - 5.2 MiB bigrat - 4.9 MiB Math::BigRat - 4.8 MiB ExtUtils::MM_NW5 - 4.7 MiB ExtUtils::MM_OS2 - 4.6 MiB ExtUtils::MM_Win32 - 4.6 MiB ExtUtils::MM_Win95 - 4.6 MiB
答案 1 :(得分:1)
您没有留下任何细节,但您已经回答了一般性问题:是的,使用大量模块会消耗大量内存,具体取决于这些模块是什么以及它们导入的内容。当然,如果使用较少的模块,或者有选择地导入符号(或根本没有),您将使用更少的内存。
你能提供一个更具体的例子来消耗比你想象的更多的内存吗?
答案 2 :(得分:-1)
要回答:我该如何减少它? (使用'使用模块(功能)'?)
当您需要使用“my_module”中的每个模块时,可能只需使用“require”,而不是大量的“使用”。这就是我减少时间/尺寸的方法。也就是说,如果您不需要在“my_module”中“使用”的每个模块。