为什么我的'使用my_module;'拿这么多堆内存?

时间:2010-02-03 22:16:26

标签: perl memory

此示例脚本:

#!/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;'在里面。

如何找到需要这么多内存的内容?

我该如何减少它? (使用'使用模块(功能)'?)

感谢您的帮助。

3 个答案:

答案 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中的模块列表,并为每个模块将子项分配给requireimport并检查它自己的堆。

#! /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”中“使用”的每个模块。