How to find which rule take long time to finish

Viewed 400

We have around 15,000 rules running and it takes 2 hours to complete. I would like to figure out which rule takes long time. Its not possible for me to go to each rule and log it. So I implemented the AgendaEventListener and override afterMatchFired() method. I know which rules fired. But how do I know which rule took long time.

3 Answers

If you want the time to execute the match, update your listener to implement the beforeMatchFired method as well. When the beforeMatchFired method triggers, start the timer. When the same rule's afterMatchFired triggers, stop the timer and log it. You'll want to also track match cancelled to discard unnecessary timers.

Remember to track this on a per-rule basis -- you'll need to identify each rule uniquely (package + name should be specific enough). Note that this exercise will get a little complicated if you have rules that extend other rules.

Rather that doing your own profile, you should take a look at the new drools-metric module that solves exactly your problem.

From the manual

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 Drools 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 Drools 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:

Try RulesChronoAgendaEventListener and RulesChronoChartRecorder from da-utils

Both gives you real-time JMX monitoring, showing average and max execution time for each rule. Second gather jfreechart data to show you values in time, which gives you perfect sense of overall performance and 'problematic' cases.

Register session listener

AgendaEventListener rulesChrono = new RulesChronoChartRecorder().withMaxThreshold(500).schedule();
session.addEventListener(rulesChrono);

Print per rule statistic

StringBuilder sb = new StringBuilder();
rulesChrono.getPerfStat().values()
        .forEach(s -> sb.append(format("%n%s - min: %.2f avg: %.2f max: %.2f activations: %d", s.getDomain(), s.getMinTimeMs(), s.getAvgTimeMs(), s.getMaxTimeMs(), s.getLeapsCount())));
System.out.println(sb.toString());

Draw charts

Map<String, TimeSeries> rulesMaxChart = rulesChrono.getRulesMaxChart();
Map<String, TimeSeries> rulesMinChart = rulesChrono.getRulesMinChart();
rulesChrono.getRulesAvgChart().entrySet()
        .forEach(e -> ChartUtils.pngChart(format("charts/%s.png", e.getKey()), 1024, 500, e.getValue(), Color.black, rulesMaxChart.get(e.getKey()), Color.lightGray, rulesMinChart.get(e.getKey()), Color.lightGray));

For the second you'll need jfreechart dependency

Related