【问题标题】:Why is my Perl regex using so much memory?为什么我的 Perl 正则表达式使用这么多内存?
【发布时间】:2010-09-15 00:07:54
【问题描述】:

我正在针对一个大标量运行正则表达式。虽然这场比赛没有捕获任何东西,但这场比赛之后我的进程增长了 30M:

# A
if (${$c} =~ m/\G<<\s*/cgs)
{
    #B
    ...
}

$c 是对一个相当大的标量(大约 21M)的引用,但我已经验证 pos(${$c}) 位于正确的位置,并且表达式在第一个字符处匹配,pos(${$c}) 被更新为比赛结束后的正确位置。但正如我所提到的,这个过程在#A 和#B 之间增长了大约 30M,即使我没有用这场比赛捕捉到任何东西。我的记忆去哪儿了?

编辑:是的,使用$&amp; 是罪魁祸首。我们使用的是 Perl 5.8.8,而我的脚本使用的是 Getopt::Declare,它使用了内置的 Text::Balanced。该模块的 1.95 版本使用 $&amp;。 Perl 5.10 附带的 2.0.0 版本删除了对 $&amp; 的引用并缓解了该问题。

【问题讨论】:

    标签: regex perl memory-management


    【解决方案1】:

    只是快速检查一下,您是否在代码中的任何位置提到了 $&、$` 或 $'(有时称为 $MATCH、$PREMATCH 和 $POSTMATCH)?如果是这样,Perl 将为 每个 正则表达式匹配复制整个字符串,以防万一你想检查这些变量。

    在这种情况下,“在你的代码中”是间接的,包括使用引用这些变量的模块,或者写use English而不是use English qw( -no_match_vars )

    如果您不确定,可以使用Devel::SawAmpersand 模块来确定它们是否已被使用,并使用Devel::FindAmpersand 来确定它们在在哪里被使用。

    内存增加可能还有其他原因(您使用的是哪个版本的 Perl?),但是如果使用匹配变量,它们肯定会破坏您的内存,因此可能是罪魁祸首。

    欢呼,

    保罗

    【讨论】:

    • 当然看起来就是这样。我无法在我的 perl 上运行 FindAmpersand,因为我启用了线程,所以我重新编译 perl 只是为了运行这个测试,但 SawAmpersand 报告是。
    • grep 或 ack 也应该能够告诉您它们是否在您的代码中的任何地方被提及。
    • 试过了,在我的代码中没有找到任何东西,所以最后开始搜索@INC中的所有库,最后缩小到使用$&的GetOpt::Declare。摆脱那个库对解决我的内存使用问题大有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-12
    • 1970-01-01
    相关资源
    最近更新 更多