Drools 由于计算分数过长,提前终止基准测试

Drools 由于计算分数过长,提前终止基准测试,drools,optaplanner,Drools,Optaplanner,我想要实现的目标 目前,我在OptaPlanner项目中运行大量输入,由于当前实施的约束,甚至计算初始分数都需要很长时间。因此,给定的解算器会破坏整个基准,因为它会被卡住,无法终止。作为分数计算类型,我使用Drools 我正在尝试提前终止一个解算器,该解算器在经过一定时间后仍未通过初始分数计算(未显示“解算已开始”)。因此,在一个基准测试中,我希望运行多个不同的输入,对于每个输入,我希望有一个给定的计时器,如果计时器在初始分数计算完成之前过期,我希望解算器立即终止。一个理想的选择是计算完成分数的

我想要实现的目标

目前,我在OptaPlanner项目中运行大量输入,由于当前实施的约束,甚至计算初始分数都需要很长时间。因此,给定的解算器会破坏整个基准,因为它会被卡住,无法终止。作为分数计算类型,我使用Drools

我正在尝试提前终止一个解算器,该解算器在经过一定时间后仍未通过初始分数计算(未显示“解算已开始”)。因此,在一个基准测试中,我希望运行多个不同的输入,对于每个输入,我希望有一个给定的计时器,如果计时器在初始分数计算完成之前过期,我希望解算器立即终止。一个理想的选择是计算完成分数的百分比

我之所以不跳起来做优化,是因为我想有一个比较基准,并在优化过程中跟踪结果。因此,初始分数计算的通过率对我来说至关重要

我目前拥有/知道的

  • 我使用的OptaPlanner版本是GitHub的版本,它的全部源代码都是开放的(不是网站上的官方版本,它是用JAR编译的,核心是不可编辑的)
  • 为基准的每个解算器实现计时器,在给定时间段后调用
    solver.terminateEarly()
    方法
  • 每个解算器在其唯一的线程上运行。因此,关系求解器:线程是1:1。查找当前执行代码的解算器的方法是在
    Map solverMap
    中进行查找,其中键是执行解算器的线程的hashCode值->
    thread.currentThread().hashCode()
    。当解算器开始和完成时,将更新此贴图。通过这种方式,我可以从所有位置进行查找(optaplanner示例、optaplanner核心、optaplanner基准项目和Drools规则(下面的示例))
  • 从Drools文档中找到用于立即终止规则执行的
    kcontext.getKieRuntime().halt()
  • 实施的专门规则将在每次更改规划/阴影实体后到达then零件,并从then零件首先检查解算器是否提前终止(由相应的计时器终止),如果是调用
    kcontext.getKieRuntime().halt()
    。例如:
  • 在下面的规则中,每次更改shiftasignment实例后,将到达then部分,如果解算器设置为提前终止,则规则执行将停止

    salience 1 //so that it is triggered first
    rule "ShiftAssignmentChange"
        when 
            ShiftAssignment()   
        then 
        if(TerminateBenchmarkEarly.solverMap.get(Thread.currentThread().hashCode()).isTerminateEarly()){
            kcontext.getKieRuntime().halt();//This command is used to terminate the fire loop early.    
        }   
    end
    
    这些规则的目的是,它们具有
    显著性1
    ,而不是默认选项0,因此它们将是第一个执行的规则,并且规则执行将立即停止 6.调用
    org.optaplanner.core.impl.score.director.drools.DroolsScoreDirector calculateScore
    方法返回执行的规则数。我可以用这个指标作为初始得分的基准。随着优化的进行,预计这个数字会越来越高,花费的时间也会越来越少

    我目前面临的问题

    我所遇到的问题是,即使再次实现了此功能,也需要花费大量时间才能达到规则中的检查,或者在某些情况下由于OutOfMemory错误而崩溃。打开Drools的Trace选项后,我可以看到它将事实插入工作内存的时间减少了一部分,然后它不断地输出
    Trace BetaNode stagedInsertWasEmpty=false
    。问题在于
    org.optaplanner.core.impl.score.director.drools.DroolsScoreDirector calculateScore
    方法中的
    kieSession.fireAllRules()
    调用,
    fireAllRules
    的代码来自drools核心,该代码被编译到一个JAR中,因此无法编辑

    结论

    无论如何,我知道这在某种程度上是一种黑客行为,但正如我上面所说,我需要这些信息作为基线,以了解我当前的解决方案在哪里,并在优化过程中跟踪基准信息。 如果有不同的(更聪明的)方法,我可以做到这一点,我会很高兴这样做

    基准测试结果

    输入1

    • 实体数:12870
    • 可变计数:7515
    • 最大值计数:21
    • 问题量表:22068
    • 加载inputSolution后(创建解算器之前)的内存使用率:平均44830840字节
    • 施工后平均得分计算速度=1965/秒
    • 本地搜索后的平均分数计算速度=1165/秒
    • 求解器完成后的平均分数计算速度=1177/秒
    输入2

    • 实体数:17559
    • 可变计数:7515
    • 最大值计数:8
    • 问题量表:21474
    • 加载inputSolution后(创建解算器之前)的内存使用率:平均5964200字节
    • 施工后平均得分计算速度=1048/秒
    • 本地搜索后的平均分数计算速度=1075/秒
    • 求解器完成后的平均分数计算速度=1075/秒
    投入3

    • 实体数:34311
    • 可变计数:14751
    • 最大值计数:8
    • 问题量表:43358
    • 加载inputSolution后(创建解算器之前)的内存使用率:平均43178536字节
    • <