代码之家  ›  专栏  ›  技术社区  ›  Evan Carroll

为什么即使符号是在本地导入的,符号的包限定也会导致更少的内存使用?

  •  0
  • Evan Carroll  · 技术社区  · 3 年前

    注意,我试过了 testing this before in this question which may look similar 然而,这些结果存在缺陷 result of constant folding, which I subsequently disabled. 并在这个问题中重新发布。


    考虑到这两个eval(执行时的注释一)只会改变 &Module::FOO() &FOO() .

    # Symbols imported, and used locally.
    eval qq[ 
      package Foo$num;
      Module->import();
      my \$result = &Module::FOO() * &Module::FOO();
    ] or die $@;
    
    # Symbols imported, not used locally referencing parent symbol.
    eval qq[ 
      package Foo$num;
      Module->import();
      my \$result = &FOO() * &FOO();
    ] or die $@;
    

    为什么顶块会占 基本上 更少的空间?脚本和输出如下所示,

    脚本

    package Module {
      use v5.30;
      use warnings;
      use constant FOO => 42; 
      use Exporter 'import';
      our @EXPORT = ('FOO');
    }
    
    
    package main {
      use v5.30;
      use autodie;
      use warnings;
    
      $|=1;
      say "Our PID is $$";
    
      for my $num ( 0..1e5 ) { 
        eval qq[ 
          package Foo$num;
          Module->import();
          my \$result = &Module::FOO() * &Module::FOO();
        ] or die $@;
        eval qq[
          package Foo$num;
          Module->import();
          my \$result = &FOO() * &FOO();
        ] or die $@;
      }
    
      say "DONE";
    
      _debug();
    
    }
    
    sub _debug {
      open my $fh, "<", "/proc/$$/status";
      while ( <$fh> ) { 
        next unless /Rss/;
        print;
      }
    }
    

    结果

    包(命名空间)已限定

    RssAnon:     101856 kB
    RssFile:       5228 kB
    RssShmem:         0 kB
    

    本地进口

    RssAnon:     151528 kB
    RssFile:       5224 kB
    RssShmem:         0 kB
    

    更新

    它是由 aquanight irc.freenode.net/#perl 尝试这个实验 constant 这是我使用的代码,

    eval qq[ 
      package Foo$num;
      use constant FOO => 42;
      my \$result = &FOO() * &FOO();
    ] or die $@; 
    eval qq[ 
      package Foo$num;
      use constant FOO => 42;
      my \$result = &Foo${num}::FOO() * &Foo${num}::FOO();
    ] or die $@;
    

    有了这个 二者都 这样执行的示例,要清楚的是,直接使用带有常量的变量并使用包限定访问常量实际上更糟糕,然后创建另一个包,该包具有该包的常量和包限定。

    Our PID is 204846
    RssAnon:     143560 kB
    RssFile:       5196 kB
    RssShmem:         0 kB
    
    0 回复  |  直到 3 年前
        1
  •  4
  •   Evan Carroll    3 年前

    导出整个符号

    如果你出口,你似乎可以非常接近 整个符号 而不是地球仪上的一个插槽,

    our @EXPORT = ('*FOO');
    

    重新运行相同的测试,你会发现两者非常相似

    RssAnon:      93900 kB
    RssFile:       5228 kB
    RssShmem:         0 kB
    

    事实上,这更接近理论上的最大值,这消除了对 import 完全地,

    eval qq[
      package Foo$num;
      my \$result = &Module::FOO() * &Module::FOO();
    ] or die $@;
    

    其产生,

    RssAnon:      74528 kB
    RssFile:       5160 kB
    RssShmem:         0 kB
    

    也许,最大的黑魔欢乐。

    然而,如果我们按照 aquanight ,

    our sub FOO;      # top of file
    Module->import();
    
    package Bar;
    print FOO();      # works
    print Bar::FOO(); # does not work
    

    符号 FOO 可用于打包 Bar 没有膨胀 酒吧 包裹。当这种方法应用于上述基准测试时,

    eval qq[
      our sub FOO ();
      Module->import();
      package Foo$num;
      my \$result = FOO() * FOO();
    ] or die $@;
    

    并产生这些结果,

    RssAnon:      75112 kB
    RssFile:       5284 kB
    RssShmem:         0 kB
    

    constant.pm ,

    这可以进一步实现为,

    eval qq[
      our sub FOO ();
      use constant FOO => 42;
      package Foo$num;
      my \$result = FOO() * FOO();
    ];
    

    这将产生这些结果,

    RssAnon:      75076 kB
    RssFile:       5180 kB
    RssShmem:         0 kB
    
    推荐文章