出于可维护性,可读性和易用性的考虑,我将分数计算器重写为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
我知道这些缓慢的规则构成了瓶颈,并使整个流口水分数的计算变慢了,但是我不知道为什么这些规则是瓶颈。我唯一能想到的是,我在慢速规则中调用方法,而在快速规则中则没有。
这是为什么调用对象方法的规则要慢得多的原因吗?如果是,为什么,我该怎么办?
谢谢!
答案 0 :(得分:1)
isServicable()
的作用是什么?它可能做的远不止return servicable;
。
关于第二个慢规则,它是Shift
和Vehicle
的叉积的累加。积累有点慢(虽然不如insertLogical
慢,但仍然如此)。
一旦发布它们,看看 ConstraintStreams 如何影响这些性能基准将很有趣。