首页 > 解决方案 > Optaplanner Drools 性能相当慢

问题描述

为了可维护性、可读性和易用性,我已经将我们的分数计算器重写为 Drools,我发现它的性能仅比我们的稍好,EasyScoreCalculator并且比我们的IncrementalScoreCalculator. (切换到 Drools 的主要原因是未能在 中实施新规则IncrementalScoreCalculator)。

这是一个比较:

得分速度比较

请注意,Drools 仅比 Easy 快一点,而 Incremental 比这两者都快约 8-10 倍。

我们有很多规则,请注意,虽然有些规则与增量规则差不多或快,但有些规则确实很慢,可能会形成瓶颈。

这是一个快速规则的示例(~18-20 k calcs/sec)

rule "The volume of all orders can't exceed the volume of the van"
    when $vehicle : Vehicle($capacity : capacity)
      accumulate(
        Customer(
          vehicle == $vehicle,
          $demand : demand);
        $demandTotal: sum($demand);
        $demandTotal > $capacity
      )
    then
      scoreHolder.addHardConstraintMatch(kcontext, 2, -Math.round($demandTotal - $capacity));
end

这是一个非常慢的规则示例(~1k calcs/sec)

rule "A shipment cannot be serviced outside of the shift's service hours"
  when
    $c: TimeWindowedCustomer( vehicle != null, this.isServicable() == true);
  then
    scoreHolder.addHardConstraintMatch(kcontext, 0, -1);
end

还有一个非常慢的规则的例子:

rule "Total used volume in future shifts"
  when
    $shift: Shift(isCurrent() == false)
    $vehicle: TimeWindowedVehicle($shift == shift, $capacity: capacity)
    accumulate(
      Customer(
         vehicle == $vehicle,
         $demand : demand);
      $demandTotal: sum($demand);
      $demandTotal > 0
    )
  then
    int utilisedFutureShiftVolumePenalty = Params.App.Solver.Scoring.utilisedFutureShiftVolumePenalty;
    long score = - utilisedFutureShiftVolumePenalty * Math.round($demandTotal);
    scoreHolder.addSoftConstraintMatch(kcontext, 1, score);
end


我知道这些缓慢的规则会形成瓶颈并减慢整个流口水分数的计算,但我无法弄清楚为什么这些规则会成为瓶颈。我唯一能想到的是,我在慢速规则中调用了一个方法,而在快速规则中我没有。

这是为什么调用对象方法的规则比其他方法慢得多的原因吗?如果是,为什么以及我应该怎么做?

谢谢!

标签: droolsoptaplanner

解决方案


做什么isServicable()?它的作用可能远不止return servicable;.

至于第二个慢规则,它是 和 的叉积的Shift累加Vehicle。累积有点慢(不像insertLogical,但仍然慢)。

一旦我们发布它们,看看ConstraintStreams如何影响这些性能基准将会很有趣。


推荐阅读