Reputation: 1934
For maintainability, readability and easy of use I have rewritten our score calculators to Drools and I find that it performs only marginally better than our EasyScoreCalculator
and is significantly slower than our IncrementalScoreCalculator
. (The main reason of switching to Drools is failing to implement a new rule in the IncrementalScoreCalculator
).
Here is a comparison:
Note that Drools is only marginally faster than Easy and that Incremental is ~8-10 times faster than either.
We have quite a few rules and note that while some rules are about as fast or faster than Incremental some are really slow and likely form a bottleneck.
Here is an example of a fast rule (~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
Here is an example of a really slow rule (~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
And another example of a really slow rule:
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
I understand that these slow rules form a bottleneck and slow the entire drools score calculation down but I can't figure out why these rules are a bottleneck. The only thing I can think of is that I call a method in the slow rules whereas in the fast ones I don't.
Is this a reason as to why a rule that calls an object method is much slower as otherwise? If yes, why and what should I do about it ?
Thanks!
Upvotes: 0
Views: 440
Reputation: 27327
What does isServicable()
do? It probably does far more than just return servicable;
.
As for the second slow rule, it's an accumulate on the cross product of Shift
and Vehicle
. Accumulates are a bit slow (not as slow as insertLogical
, but still).
It will be interesting to see how ConstraintStreams affect these performance benchmarks, once we release them.
Upvotes: 1