为了可维护性,可读性和易用性,我将我们的分数计算器重写为Drools,我发现它的表现仅略高于我们的EasyScoreCalculator
,并且明显慢于我们的IncrementalScoreCalculator
。 (切换到Drools的主要原因是未能在IncrementalScoreCalculator
中实施新规则)。
这是一个比较:
请注意,Drools仅略微快于Easy,而Incremental比任何一个快〜8-10倍。
我们有相当多的规则并注意到虽然有些规则与Incremental一样快或者快,但有些规则确实很慢并且可能形成瓶颈。
这是一个快速规则的例子(~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计算/秒)
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
我知道这些缓慢的规则形成了一个瓶颈,并且减缓了整个流氓计分的计算速度,但我无法弄清楚为什么这些规则是瓶颈。我唯一能想到的是,我在缓慢的规则中调用一种方法,而在快速的规则中,我没有。
这是一个原因,为什么调用对象方法的规则要慢得多?如果是,为什么以及我该怎么做呢?
谢谢!
isServicable()
做什么?它可能远远超过return servicable;
。
至于第二个缓慢的规则,它是Shift
和Vehicle
的交叉积累。积累有点慢(不像insertLogical
那么慢,但仍然)。
一旦我们发布它们,看看ConstraintStreams如何影响这些性能基准将会很有趣。