k88
k88

Reputation: 1934

Optaplanner Drools performance is rather slow

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:

Score speed comparisons

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

Answers (1)

Geoffrey De Smet
Geoffrey De Smet

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

Related Questions