You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何AnyEvent出现性能下降或内存泄漏问题?

AnyEvent + EV 环境下IO监视器内存泄漏问题分析与解决

编写兼容AnyEvent的Perl模块时,基准测试显示性能随时间急剧下降,关闭AnyEvent后问题消失,最终定位到这段代码:

if (USING_AE) {
    my $cv = AE::cv();
    my $t = AE::timer($self->time_left, 0, $cv)
        if $self->has_timeout;
    my $w = AE::io($self->[SOCK], $mode ? 1 : 0, $cv);
    $cv->recv; # 阻塞至事件触发或超时
}

现象类似内存泄漏,但在$cv->recv后显式undef所有变量无效。由于无超时场景下计时器不会创建,问题锁定在条件变量(CV)与IO监视器之间。

为排查,我给IO监视器加了弱引用,按逻辑代码块退出时它应被销毁,但实际仍有对象持有其引用——这意味着IO监视器被不断创建却无法回收,正是性能下降的原因,但根源在哪?

进一步测试发现,泄漏仅在EV实现中出现,纯Perl实现无此问题。难道是EV的bug?


问题根源与解决方案

根源:当调用$cv->recv时,EV会将该CV标记为「当前活跃的条件变量」,并在内部保留一个强引用。而代码中直接将$cv作为IO监视器的回调,导致IO监视器也持有$cv的强引用;EV内部的引用会连带保留$cv,进而保留IO监视器,最终导致两者都无法被垃圾回收。

解决方法:将IO监视器的回调改为匿名子例程,显式调用$cv->send,避免直接传递$cv作为回调:

my $w = AE::io($self->[SOCK], $mode ? 1 : 0, sub { $cv->send });

这样IO监视器的回调仅持有$cv的弱引用,代码块退出后,$cv和$w都会被正常回收,内存泄漏问题解决。


内容的提问来源于stack exchange,提问作者TFBW

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 08:27:34