perl - 为什么符号的包限定会导致使用的内存更少,即使符号是在本地导入的?
问题描述
请注意,我之前在这个问题中尝试过测试它可能看起来相似,但是这些结果有缺陷并且是不断折叠的结果,我随后禁用了它。并在此问题中重新发布。
鉴于这两个仅更改&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
on要求直接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
解决方案
导出整个符号
如果您导出整个符号而不是全局中的一个插槽,您似乎可以非常接近,
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
而不会使包装膨胀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
推荐阅读
- python - 拆分日期时间索引以识别连续时间戳(Python)
- python-3.x - 在指定日期范围内移动聚合
- mysql - MySQL中Spring Boot Hibernate的乐观锁情况死锁
- angular - 为什么在构造函数的参数中需要私有访问器?
- python - Pandas 滚动 Python 以创建新列
- php - 如何使用 2 个输入文件创建多个上传文件
- javascript - firebase 函数通过流从网络上传文件仅部分工作
- groovy - groovy:: 复合 if 语句不评估为真
- javascript - 如何获取角度可观察的状态码
- installation - 错误:grub-efi-amd64-已在 Ubuntu 20.04 中签名。尝试安装软件包