为什么我的 Drools 应用程序对 JoinNodeLeftTuple 对象使用大量内存,如何优化我的规则?

问题描述 投票:0回答:1

我正在开发基于 Drools 的应用程序,并且内存使用率很高,特别是由于堆中存在大量 JoinNodeLeftTuple 对象。这似乎与我正在寻找的事件数量成比例。例如,当我查找 5,000 个事件时,会产生大约 250 万个 JoinNodeLeftTuple 对象,而当我将搜索增加到 10,000 个事件时,JoinNodeLeftTuple 对象的数量会跃升至 3100 万个。

这是我的规则之一:

rule "Attack 50113 - Level 5 - ID 4"
when
    $scenario: Scenario(sid == 50113, rid == 3)
    $prevLevel: Attack() from $scenario.lastAttack
    Number(this >= 4000) from accumulate(
              $a : RequestEvent(sourceIp == $scenario.getAttack(0).sourceIp, pluginId == 4003, pluginSid == 1, this after[1ms, 86400s] $prevLevel),
              count($a)
    )

    $clock: PseudoClockScheduler()
then
    ...
end

之前,我从这些累积的 RequestEvent 中形成了一个数组列表,并将它们存储在我创建的下一个 Attack 对象中。我删除了它们,它似乎对垃圾收集没有任何影响。 现在,我正在转储堆并使用 Eclipse 内存分析器对其进行分析。这是使用上述规则得出的直方图: 堆转储直方图

我的问题是:

  1. 在规则中使用带有时间窗口的累积是否可能是与 JoinNodeLeftTuple 对象相关的高内存使用率的原因?
  2. 是否有其他方法可以更节省内存地对事件进行计数,从而可能避免积累如此多的 JoinNodeLeftTuple 对象?

如有任何建议,我们将不胜感激。

编辑:

这是一个总共 5000 个日志的简单示例,它应该会产生 250 万个 JoinNodeLeftTuple 对象,这就是我试图找出原因的原因。

查看github存储库

我知道这些元组对象具有对接收器的引用,并且从我在内存分析器中看到的,它们的接收器是累积节点。所以,作为我第一个问题的简单答案,是的!累积节点负责这些元组。

drools complex-event-processing
1个回答
0
投票

有趣的收获...
我已经重现了这个问题。
首先,您能否通过从依赖项中删除 api 6 来删除混合 drools api 6 和 core 8 库版本。
然后可以通过修复导入来解决找不到类的问题

import org.kie.api.time.SessionClock;
import org.drools.core.time.SessionPseudoClock;
import org.drools.core.time.impl.PseudoClockScheduler;

我还没有解决这个问题(这是一个问题吗?)。
如果忽略对象的极值计数,您是否会遇到 OOM 错误?
如果是这样,您可以使用模式数据更新您的事件文件来体验它吗? 您可以尝试在插入一些数据后添加 System.gc() 吗,它会放松吗? (我的意思是对象的计数还不是问题,这些可能是易失性对象)

虽然我已经达到了一定程度,但是很难对逻辑进行逆向工程。您能否解释一下“我们已经有了最后一个场景”的逻辑。规则?

© www.soinside.com 2019 - 2024. All rights reserved.