这个问题与Perl的answer到前question about memory handling有关。我已经了解到可以通过在可用标量上显式使用undef
函数并使用Devel::Peek
或Devel::Size
来释放Perl中的内存,或者这样可以查看为a分配了多少内存标量。在所有这些情况下,调试的标量都在其范围内使用。
但是有可能在变量范围之外调试分配内存之类的东西,只是在Perl解释器的层次上?有点像为当前解释器中的标量搜索所有“事物”的所有已分配内存并打印其相关数据,如当前值等?
如果是这样的话,如果一个人已经拥有这些信息,那么是否能够释放已知的内存?就像在标量上调用undef
一样,但没有标量,更低级别的东西,比如Devel::Peek
的那些“东西”输出。
我正在考虑的是在请求之后执行mod_perl清理处理程序,扫描当前mod_perl解释器以获取大块数据并手动释放它们。仅仅因为我认为大块分配的数据不再有用,即使Perl认为不是这样:
最后也许最大的胜利是内存重用:当调用Perl子程序时,内存分配是在第一次使用它们时为变量做出的。随后使用变量可以分配更多的内存,例如如果标量变量需要保存比之前更长的字符串,或者数组中添加了新元素。作为优化,Perl会挂起这些分配,即使它们的值“超出范围”。
https://perl.apache.org/docs/2.0/user/intro/overview.html#Threads_Support
我可以找到很多关于低级内存访问的监视和调试包,但是没有提示如何在Perl中的某些低级Perl结构上调用类似undef
函数的东西。没有任何XS或其他可能根本不可能......
答案 0 :(得分:4)
是否可以在变量范围之外调试分配的内存
真的没有这样的记忆。肯定需要在变量之外分配的任何内存。正如你自己指出的那样,它是为构成最“浪费”空间的变量分配的内存。
但是没有提示如何在Perl中的某些低级Perl结构上调用undef函数。
这是因为没有这样的结构。
就像在标量上调用
undef
一样,但没有标量,更低级别的东西,比如Devel :: Peek的那些“东西”输出。
Devel :: Peek唯一的函数Dump
,在变量中输出。就像你说的那样,undef
就是你要清除它们的东西。
从上面可以看出,你很想知道如何释放与变量相关的内存。
您还忽略了这样一个事实:许多运算符都有一个关联变量(称为“目标”),在这些变量中它们返回结果。
清除所有这些变量的一种简单方法是选择性地清除符号表(%::
)。这将有效地“卸载”每个模块。请务必清除核心组件(perl -E'say for sort keys %::'
)。并且不要忘记清除%INC
以便重新加载模块。
如果清除符号表是您想要采用的方法,那么在早期拍摄%::
快照可能会降低风险和时间,并在清除符号时恢复该快照。
如果您不想重新加载模块,可以尝试找到每个子组,并取消其变量,然后取消其操作的变量。
子{v}存在于其pads内。方便的是,操作码目标也是如此。对于子经历的每个级别的递归都有一个填充。
给定对sub的引用,您可以在子垫中找到变量。您可以参考PadWalker获取如何执行此操作的示例。您实际上不能使用PadWalker,因为它只返回每个变量名称一个变量,即使有多个变量名称(由于多个变量声明的名称相同,或者由于递归)。
捕获的变量和our
变量应保持不变。可以检测填充条目是否是其中之一。 (再次,请参阅PadWalker。)
(显然,你也可以考虑释放sub的额外垫!)
你如何找到所有潜艇?那么,导航符号表将为您提供大部分。寻找一个人将会更加棘手。
最有效的方法是简单地终止mod_perl线程/进程。将自动生成一个新的干净的。它也是最简单的实现,因为它只是一个配置更改(将MaxRequestsPerChild
设置为1
)。
另一种形式的浪费内存是内存泄漏。这是另一个大问题,所以我没有触及它。
答案 1 :(得分:1)
我认为您正在寻找类似问题this answer。 你真正需要知道的一切都可以在Devel :: MAT :: *子模块的内部找到。即Devel::MAT::Dumper.xs,它具有perl解释器的堆结构。该模块旨在将堆转储到信号并稍后进行分析,但我认为您可以将其转换为运行时检查。如果您在阅读XS时需要帮助,请查看here。
答案 2 :(得分:-1)
要调试内存分配,您应该使用-Accflags=-DPERL_MEM_LOG
DOC
(参见有关how to recompile perl的相关问题)
您可能会对MEMORY DEBUGGERS
感兴趣释放perl标量,就像它离开她的范围一样:
{ # Scope enter
my $x; # Memory allocation
} # << HERE $x is freed
您应该通过REFCNT
宏DOC将其变量SvREFCNT_dec
减少为零
要释放您已创建的SV,请调用SvREFCNT_dec(SV *)。通常这种调用是不必要的(参见参考计数和死亡率)。
这是伪代码:
{
$x;
call_xs_sub( $x ); # << HERE $x is freed
}
XS伪代码:
call_xs_sub( SV *sv ) {
...
SvREFCNT_dec( sv ); # <<HERE scalar is freed
...
}
要窥探每个内存分配,你应该走perl竞技场。
在编译时,您可以在B::Xref模块的帮助下查看声明和访问变量的每个位置
或者使用-Dm
选项运行perl(perl应该使用相应的选项进行编译。请参阅topic):
perl -Dm script.pl