Chapter 22. 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 ofPerson( "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 16.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 patternPerson( firstName == "John" )
is evaluated more efficiently thanPerson( 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 16.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
clausewhen $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
clausewhen $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 16.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. Thedrools-metric
module can also assist in analyzing the decision engine performance. Note that thedrools-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
, first adddrools-metric
to your project dependencies:Example project dependency for
drools-metric
<dependency> <groupId>org.drools</groupId> <artifactId>drools-metric</artifactId> </dependency>
If you want to use
drools-metric
to enable trace logging, configure a logger fororg.drools.metric.util.MetricLogUtils
as shown in the following example:Example logback.xml configuration file
<configuration> <logger name="org.drools.metric.util.MetricLogUtils" level="trace"/> ... <configuration>
Alternatively, you can use
drools-metric
to expose the data using Micrometer. To expose the data, enable the Micrometer registry of your choice as shown in the following example:Example project dependency for Micrometer
<dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-jmx</artifactId> <!-- Discover more registries at micrometer.io. --> </dependency>
Example Java code for Micrometer
Metrics.addRegitry(new JmxMeterRegistry(s -> null, Clock.SYSTEM));
Regardless of whether you want to use logging or Micrometer, you need to enable
MetricLogUtils
by setting the system propertydrools.metric.logger.enabled
totrue
. Optionally, you can change the microseconds threshold of metric reporting by setting thedrools.metric.logger.threshold
system property.NoteOnly node executions exceeding the threshold are reported. The default value is
500
.After configuring the
drools-metric
to use logging, 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. WhenevalCount
is used with Micrometer, a counter with the data is calledorg.drools.metric.evaluation.count
. -
elapsedMicro
is the elapsed time of the node execution in microseconds. WhenelapsedMicro
is used with Micrometer, look for a timer calledorg.drools.metric.elapsed.time
.
If you find an outstanding
evalCount
orelapsedMicro
log, correlate the node name withReteDumper.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] ...
-