Troup Troup - 4 months ago 75
Java Question

Drools Rules Template - first invocation 1000 times slower than subsequence invocations

I have built a Drools Rules Template (http://docs.jboss.org/drools/release/6.4.0.Final/drools-docs/html_single/index.html#d0e6300) using Drools 6.4.0.Final

It is pretty much identical to the example provided:

https://github.com/droolsjbpm/drools/blob/master/drools-examples/src/main/java/org/drools/examples/decisiontable/PricingRuleTemplateExample.java

I have wrapped it in a Spring RestController and deployed it as a WAR in to Tomcat.

I notice that the first call is always very slow to get a result and gets slower as the number of rows in the xls spreadsheet grows. I imagine drools builds an index when the first ever KieSession is created. And that this index is subsequently cached making further calls much faster?

I see the same behaviour when invoking directly from unit tests. First test is slow and subsequent tests are 1000 times faster.

For example, I see first call take 30secs and every subsequent call take 20ms where the spreadsheet has ~1000 rows.

Is there a way to force this "indexing" step to happen when the web application server (Tomcat) is starting up?

Answer

In the example you have linked, there is a line that is doing more than what it appears to be doing. The line I'm talking about is:

KieSession ksession = kc.newKieSession( "DTableWithTemplateKS" );

One of the steps inside KieContainer.newKieSession() is to create the KieBase the specified KieSession belongs to. A KieBase is the binary representation of your rules. Once a KieBase is built, it can be used to spawn multiple KieSessions (their runtime counterpart). The creation of a KieBase could be very time consuming. Spawning new KieSessions from it it is not.

The KieContainer class uses an internal Map to keep a reference to the KieBases that were already built. The first time you ask KieContainer for a KieSession the KieContainer has first to build the KieBase. Following invocations of newKieSession() will reuse the KieBase already built. Note that this is true as long as you always ask for the same KieSession. Try having multiple KieBases and ask for different KieSessions from them and you will see that the first time you ask for a KieSession from a new KieBase you will experience this delay.

One thing you could do is to ask KieContainer for your KieBase when your app is starting. You can do this by either executing kc.newKieSession( "XXX" ); or kc.getKieBase("YYY");

Hope it helps,

Comments