Chapter 20. Performance tuning considerations with DRL

The following key concepts or suggested practices can help you optimize DRL rules and decision engine performance. These concepts are summarized in this section as a convenience and are explained in more detail in the cross-referenced documentation, where applicable. This section will expand or change as needed with new releases of Red Hat Decision Manager.

Define the property and value of pattern constraints from left to right

In DRL pattern constraints, ensure that the fact property name is on the left side of the operator and that the value (constant or a variable) is on the right side. The property name must always be the key in the index and not the value. For example, write Person( firstName == "John" ) instead of Person( "John" == firstName ). Defining the constraint property and value from right to left can hinder decision engine performance.

For more information about DRL patterns and constraints, see Section 14.8, “Rule conditions in DRL (WHEN)”.

Use equality operators more than other operator types in pattern constraints when possible
Although the decision engine supports many DRL operator types that you can use to define your business rule logic, the equality operator == is evaluated most efficiently by the decision engine. Whenever practical, use this operator instead of other operator types. For example, the pattern Person( firstName == "John" ) is evaluated more efficiently than Person( firstName != "OtherName" ). In some cases, using only equality operators might be impractical, so consider all of your business logic needs and options as you use DRL operators.
List the most restrictive rule conditions first

For rules with multiple conditions, list the conditions from most to least restrictive so that the decision engine can avoid assessing the entire set of conditions if the more restrictive conditions are not met.

For example, the following conditions are part of a travel-booking rule that applies a discount to travelers who book both a flight and a hotel together. In this scenario, customers rarely book hotels with flights to receive this discount, so the hotel condition is rarely met and the rule is rarely executed. Therefore, the first condition ordering is more efficient because it prevents the decision engine from evaluating the flight condition frequently and unnecessarily when the hotel condition is not met.

Preferred condition order: hotel and flight

when
  $h:hotel() // Rarely booked
  $f:flight()

Inefficient condition order: flight and hotel

when
  $f:flight()
  $h:hotel() // Rarely booked

For more information about DRL patterns and constraints, see Section 14.8, “Rule conditions in DRL (WHEN)”.

Avoid iterating over large collections of objects with excessive from clauses

Avoid using the from condition element in DRL rules to iterate over large collections of objects, as shown in the following example:

Example conditions with from clause

when
  $c: Company()
  $e : Employee ( salary > 100000.00) from $c.employees

In such cases, the decision engine iterates over the large graph every time the rule condition is evaluated and impedes rule evaluation.

Alternatively, instead of adding an object with a large graph that the decision engine must iterate over frequently, add the collection directly to the KIE session and then join the collection in the condition, as shown in the following example:

Example conditions without from clause

when
  $c: Company();
  Employee (salary > 100000.00, company == $c)

In this example, the decision engine iterates over the list only one time and can evaluate rules more efficiently.

For more information about the from element or other DRL condition elements, see Section 14.8.7, “Supported rule condition elements in DRL (keywords)”.

Use decision engine event listeners instead of System.out.println statements in rules for debug logging

You can use System.out.println statements in your rule actions for debug logging and console output, but doing this for many rules can impede rule evaluation. As a more efficient alternative, use the built-in decision engine event listeners when possible. If these listeners do not meet your requirements, use a system logging utility supported by the decision engine, such as Logback, Apache Commons Logging, or Apache Log4j.

For more information about supported decision engine event listeners and logging utilities, see Decision engine in Red Hat Decision Manager.

Use the drools-metric module to identify the obstruction in your rules

You can use the drools-metric module to identify slow rules especially when you process many rules. The drools-metric module can also assist in analyzing the decision engine performance. Note that the drools-metric module is not for production environment use. However, you can perform the analysis in your test environment.

To analyze the decision engine performance using drools-metric, add drools-metric to your project dependencies and enable trace logging for org.drools.metric.util.MetricLogUtils , as shown in the following example:

Example project dependency for drools-metric

<dependency>
  <groupId>org.drools</groupId>
  <artifactId>drools-metric</artifactId>
</dependency>

Example logback.xml configuration file

<configuration>
  <logger name="org.drools.metric.util.MetricLogUtils" level="trace"/>
  ...
<configuration>

Also, enable MetricLogUtils by setting the system property drools.metric.logger.enabled to true. Optionally, you can change the microseconds threshold of metric logging by setting the drools.metric.logger.threshold system property.

Note

Only node executions exceeding the threshold are logged. The default value is 500.

After you complete the configuration, rule execution produces logs as shown in the following example:

Example rule execution output

TRACE [JoinNode(6) - [ClassObjectType class=com.sample.Order]], evalCount:1000, elapsedMicro:5962
TRACE [JoinNode(7) - [ClassObjectType class=com.sample.Order]], evalCount:100000, elapsedMicro:95553
TRACE [ AccumulateNode(8) ], evalCount:4999500, elapsedMicro:2172836
TRACE [EvalConditionNode(9)]: cond=com.sample.Rule_Collect_expensive_orders_combination930932360Eval1Invoker@ee2a6922], evalCount:49500, elapsedMicro:18787

This example includes the following key parameters:

  • evalCount is the number of constraint evaluations against inserted facts during the node execution.
  • elapsedMicro is the elapsed time of the node execution in microseconds.

If you find an outstanding evalCount or elapsedMicro log, correlate the node name with ReteDumper.dumpAssociatedRulesRete() output to identify the rule associated with the node.

Example ReteDumper usage

ReteDumper.dumpAssociatedRulesRete(kbase);

Example ReteDumper output

[ AccumulateNode(8) ] : [Collect expensive orders combination]
...