Почему мой 'использует my_module;' взять столько памяти кучи? - PullRequest
2 голосов
/ 04 февраля 2010

Этот пример сценария:

#!/usr/bin/perl -w

while (1)
{
  sleep(1);
}

занимает около 264 кБ

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 кБ!

grep -A1 heap  /proc/9219maps 
0817b000-09326000 rw-p 0817b000 00:00 0          [heap]
Size:             18092 kB

Примечание: в my_module много модулей use; внутри него.

Как я могу найти то, что занимает столько памяти?

Как я могу уменьшить его? (используя 'использовать модуль (функцию)'?)

Спасибо за вашу помощь.

Ответы [ 3 ]

14 голосов
/ 04 февраля 2010

Вставьте 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 предпочитает бросать память при проблемах, и в наши дни машины обычно имеют несколько гибибайт основной памяти.

Эта проблема с ресурсом вызывает проблемы с производительностью?

Ниже приведена программа, которая просматривает список модулей в 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 голос
/ 04 февраля 2010

Вы не оставили никаких подробностей, но вы уже ответили на общий вопрос: да, использование большого количества модулей может занять много памяти, в зависимости от того, что это за модули и что они импортируют. Безусловно, вы будете использовать меньше памяти, если будете использовать меньше модулей или выборочно импортировать символы (или вообще не использовать их).

Можете ли вы привести более конкретный пример того, что потребляет больше памяти, чем, по вашему мнению, должно быть?

0 голосов
/ 04 февраля 2010

Ответить: как я могу уменьшить его?(используя 'use module (function)'?)

Вместо большого количества "use", возможно, просто используйте "require", когда вам нужно использовать каждый модуль в вашем "my_module"Это то, что я делаю, чтобы сократить время / размер.То есть, если вам не нужен каждый модуль, который вы «используете» в своем «my_module».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...