drools规则引擎在小规则文件上运行内存不足

时间:2015-06-03 20:57:53

标签: java drools rule-engine

我写了一个使用drools规则引擎的java代码。当我试图通过向规则文件(.drl)添加越来越多的规则来测试代码的性能时。当我在14MB规则文件中打包100000个规则时,程序停止工作。

我的规则文件如下所示(模拟规则):

package drools.rules

import drools.DicomImage

rule "PHI rule0"

    when
        $di : DicomImage(boolName == true)
    then
        System.out.println("rule 0 is applied");
end

rule "PHI rule1"

    when
        $di : DicomImage(boolName == true)
    then
        System.out.println("rule 1 is applied");
end

rule "PHI rule2"

    when
        $di : DicomImage(boolName == true)
    then
        System.out.println("rule 2 is applied");
end

以下是适用规则的代码:

String filename = "rule100000.drl";
Reader reader = new InputStreamReader(ApplyDicomRules.class.getResourceAsStream(filename));
PackageBuilder pBuilder = new PackageBuilder();
pbuilder.addPackageFromDrl(reader);

Rulebase rbase = RuleBaseFactory.newRuleBase();
rbase.addPackage(pbuilder.getPackage());

runRules();

它在执行addPackageFromDrl的行中退出并出现以下错误:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
 at java.lang.Throwable.printStackTrace(Unknown Source)
 at org.eclipse.jdt.internal.compiler.util.Util.getExceptionSummary(Util.java:627)
 at org.eclipse.jdt.internal.compiler.Compiler.handleInternalException(Compiler.java:587)
 at org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:522)
 at org.drools.compiler.commons.jci.compilers.EclipseJavaCompiler.compile(EclipseJavaCompiler.java:405)
 at org.drools.compiler.commons.jci.compilers.AbstractJavaCompiler.compile(AbstractJavaCompiler.java:49)
 at org.drools.compiler.rule.builder.dialect.java.JavaDialect.compileAll(JavaDialect.java:405)
 at org.drools.compiler.compiler.DialectCompiletimeRegistry.compileAll(DialectCompiletimeRegistry.java:46)
 at org.drools.compiler.compiler.PackageRegistry.compileAll(PackageRegistry.java:107)
 at org.drools.compiler.compiler.PackageBuilder.compileAll(PackageBuilder.java:1317)
 at org.drools.compiler.compiler.PackageBuilder.compileAllRules(PackageBuilder.java:968)
 at org.drools.compiler.compiler.PackageBuilder.addPackage(PackageBuilder.java:956)
 at org.drools.compiler.compiler.PackageBuilder.addPackageFromDrl(PackageBuilder.java:452)
 at org.drools.compiler.compiler.PackageBuilder.addPackageFromDrl(PackageBuilder.java:428)
 at drools.ApplyDicomRules.initializeDrools(ApplyDicomRules.java:65)
 at drools.ApplyDicomRules.main(ApplyDicomRules.java:26)

即使我使用-Xms1024m运行它也不起作用。我不认为它无论如何都需要那么多的记忆。而我只是将规则应用于单个事实(对象)。

什么花了这么多公羊?我不应该将那么多规则(100000)放在一个规则文件中吗?

3 个答案:

答案 0 :(得分:0)

好吧,我不打电话给一个包含100000条规则的文件" small",根据我最喜欢的词典,这意味着数量很少或数量很少",和100000不仅仅是一些"少数"。如果这个实验有任何严重的背景,你应该重新考虑你的方法 - 很可能,你走错了路。

那就是说,Drools规则引擎并不是内存不足的:它是Java编译器,无法在单个Java文件中处理这么多的源代码。

  • 使用多个DRL文件应避免OOM问题。
  • 此外,尝试6.x版本可能会有所帮助,因为代码生成和编译在5.x和6.x之间已经发生了变化。
  • 但是,当您真正到达执行阶段时,任何包含100000的有意义的规则很可能会导致问题。

答案 1 :(得分:0)

在Drools 6.0及更高版本中,我认为它需要KIE而不是KnowledgeBase。这是我使用的东西:

     KieServices kieServices = KieServices.Factory.get();
     KieFileSystem kfs = kieServices.newKieFileSystem();
     FileInputStream fis = new FileInputStream(path to your .drl file);
     kfs.write(path to your drl file,kieServices.getResources().newInputStreamResource( fis ));
     KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll();
     Results results = kieBuilder.getResults();
    if( results.hasMessages( Message.Level.ERROR ) ){
        System.out.println( results.getMessages() );
        throw new IllegalStateException( "### errors ###" );
    }

    KieContainer kieContainer = kieServices.newKieContainer( kieServices.getRepository().getDefaultReleaseId() );
    KieBaseConfiguration config = kieServices.newKieBaseConfiguration();

但我不认为这是Java堆空间问题的根本原因! (我也面临同样的问题)

答案 2 :(得分:0)

嗨问题可能是规则的触发插入新事实并最终耗尽内存。两种处理方式: 1.添加无循环真 2.编写条件,以便仅在满足条件时才触发规则。

  

规则&#34;发出儿童通行证&#34;       当$ ch:人(年龄<10)             not(存在ChildPass(childid == $ ch.id))       然后ChildPass $ chpass = new ChildPass(); $ chpass.id = $ ch.id;插入($ CH);端