我们使用 Drools 作为解决方案的一部分,在一个非常密集的处理应用程序中充当一种过滤器,可能在 500,000 + 个工作内存对象上运行多达 100 条规则。事实证明它非常慢。其他人有在批处理应用程序中使用 Drools 的经验吗?
9 回答
取决于您的规则 - 给定足够的内存,500K 对象是合理的(它必须在内存中填充 RETE 网络,因此内存使用量是 500K 对象的倍数 - 即对象空间 + 网络结构、索引等空间) - 它可能您正在分页到磁盘,这将非常慢。
当然,如果你有匹配相同类型事实组合的规则,那可能会导致尝试组合的爆炸式增长,即使你有 1 条规则也会非常慢。如果你有更多关于你正在做的分析的信息,那可能会帮助你找到可能的解决方案。
我使用了带有状态工作记忆的 Drools,其中包含超过 100 万个事实。通过对规则和底层 JVM 进行一些调整,初始启动几分钟后性能会非常好。如果您想了解更多详情,请告诉我。
我没有使用过最新版本的 Drools(我上次使用它是大约一年前),但当时我们的高负载基准测试证明它非常慢。在我们的大部分架构都基于它之后,我们感到非常失望。
至少我记得关于 drools 的一些好处是他们的开发团队可以在 IRC 上找到并且非常有帮助,你可以试试他们,毕竟他们是专家:irc.codehaus.org #drools
我自己只是在学习流口水,所以也许我遗漏了一些东西,但是为什么整批五十万个对象一次添加到工作内存中?我能想到的唯一原因是,只有当批次中的两个或多个项目相关时才会启动规则。
如果不是这种情况,那么也许您可以使用无状态会话并一次断言一个对象。我假设在这种情况下规则的运行速度会快 50 万倍。
即使是这种情况,您的所有规则是否都需要访问所有 500k 个对象?您能否通过一次应用一项规则来加快处理速度,然后在处理的第二阶段使用不同的规则库和工作内存应用批处理级规则?这不会改变数据量,但 RETE 网络会更小,因为简单的规则会被删除。
另一种方法是在第二阶段尝试识别相关的对象组并按组声明对象,进一步减少工作内存中的数据量并拆分 RETE 网络。
Drools 并不是真正设计用于在大量对象上运行的。它针对在一些对象上运行复杂的规则进行了优化。
每个附加对象的工作内存初始化太慢,并且缓存策略旨在为每个工作内存对象工作。
使用无状态会话并一次添加一个对象?
在解析了几千个对象后,我遇到了 OutOfMemory 错误的问题。设置不同的默认优化器解决了这个问题。
OptimizerFactory.setDefaultOptimizer(OptimizerFactory.SAFE_REFLECTIVE);
我们也在研究流口水,但对我们来说,对象的数量很少,所以这不是问题。我确实记得读过相同算法的替代版本,它们更多地考虑了内存使用情况,并且针对速度进行了优化,同时仍然基于相同的算法。不过,不确定他们中是否有人将其变成了真正可用的库。
这个优化器也可以通过使用参数 -Dmvel2.disable.jit=true 来设置