Drools rule execution slowness and heap space error

432 views
Skip to first unread message

Samaresh Deyashi

unread,
May 17, 2021, 3:52:25 PM5/17/21
to Drools Usage
Hi Team,

Need help on an urgent issue. I have tried a lot but no way out. Any help is appreciated.

I am running JBoss and drools in a container hosted in azure vm(32GB RAM, 18GB Heap space). And I am executing rules using the below code in an microservice:
 
I am facing two problem:

1. I am sending more than 100000 objects in batches of 1000
after a certain time I am getting heap space issue.

2. Execution of rules are very slow

Here is java options which is already set :
-Xmx18G -Xms18G -XX:MetaspaceSize=4G -XX:MaxMetaspaceSize=4G -XX:+UseG1GC -Ddrools.multithreadEvaluation=true -Ddrools.shadowproxy=false -Ddrools.maintainTms=false
-Ddrools.sequential=true -Ddrools.maxThreads=500 -XX:+UseStringDeduplication -XX:MaxDirectMemorySize=5G 


==================Client code in Microservice to call and execute rules==========
    private KieServicesConfiguration  buildKieServicesClient(){
    KieServicesConfiguration connectionConfig = KieServicesFactory.newRestConfiguration(
    this.serverUrl, 
    this.user,
    this.password,KIESERVER_CONNECTION_TIMEOUT); 
            connectionConfig.setMarshallingFormat(KIESERVER_MARSHALLING);
            
            addExtraClasses(connectionConfig);
            return connectionConfig;
            
            
    }
    
    private void addExtraClasses(KieServicesConfiguration connectionConfig) {
       
        Set<Class<?>> extraClassList = new HashSet<Class<?>>();
        extraClassList.add(SourceData.class);  
        connectionConfig.addExtraClasses(extraClassList); 
   
    }
    
    public static KieServicesClient getKieServicesClient() {
        return kieServicesClient;
    }
    
    private void setKieServicesClient(final KieServicesClient _kieServicesClient){
        kieServicesClient = _kieServicesClient;
    }

private List<SourceData> subBatchprocess(List<SourceData> input) {
KieServicesClient kieClient=KieServicesFactory.newKieServicesClient(connectionConfig);
    RuleServicesClient client=kieClient.getServicesClient(RuleServicesClient.class);

    List<Command<?>> cmds = new ArrayList<Command<?>>();
        KieCommands commands= KieServices.Factory.get().getCommands();
   
        for(SourceData sd:input)
        {
       
        cmds.add(commands.newInsert(sd));
        
        }
       
        GetObjectsCommand getObjectsCommand = new GetObjectsCommand();       
        getObjectsCommand.setOutIdentifier("objects");
        cmds.add(getObjectsCommand);
    BatchExecutionCommand myCommands=commands.newBatchExecution(cmds,ksessionName);
   
     log.info("Calling kie server for this batch ");
    ServiceResponse<ExecutionResults> response=null;
    List<SourceData> responseList=new ArrayList<SourceData>();
    try {
         response = client.executeCommandsWithResults(ContainerId, myCommands);
         
            }catch(Exception ex)
    {
    System.out.println("### exception:executeCommandsWithResults calling got exception -"+ex.getMessage());
   
   
    }
    log.info("Received response from kie server Response:"+response.getMsg());
   
       responseList=(List<SourceData>)response.getResult().getValue("objects");
       
    return responseList;
    }
=================================================

using Kie work bench I have create a project with 
1. SourceData Class--same SourceData model class which is microservice
2. Functions Class - where all java functions are present which I am calling from ddrl file
3. DRL file- Here all drool rules are present total 40 rules present

========DRL file one sample rule=============

package com.att.hcmlink.hcmlinkruleengine;



import com.att.hcmlink.hcmlinkruleengine.SourceData.*;
import com.att.hcmlink.hcmlinkruleengine.Functions;
import java.text.ParseException;
import java.util.List;

dialect "java"

rule "ConditionMatcher"

@ConditionLHS()
@ConditionRHS()
@ConditionResult()
@DefaultColumnName()
@Hints(This rule will be used for matching condition like if ConditionLHS==ConditionRHS then use value ConditionResult else use default column value)

    when
        sourceDataInstance:SourceData(ruleName=="ConditionMatcher" && status!="Processed" && status!="Exception")
        
    then
    SourceData sd=new SourceData();
        sd=sourceDataInstance;
     try{ 
    
     sd.setStatus("Processed");
    sd.setDestColumnValue(Functions.ConditionMatcherFunction(Functions.mapLookup(sourceDataInstance.getRuleParam().get("ConditionLHS"),sourceDataInstance.getRow()),sourceDataInstance.getRuleParam().get("ConditionRHS"),sourceDataInstance.getRuleParam().get("ConditionResult"),Functions.mapLookup(sourceDataInstance.getRuleParam().get("DefaultColumnName"),sourceDataInstance.getRow())));
        
          insertLogical(sd);                
    
        retract(sourceDataInstance);
}catch(Exception e)
   {
        sd.setExMsg(e.toString());
       sd.setStatus("Exception");
        insertLogical(sd);   
       retract(sourceDataInstance);
   }
end



==============Sample function in Functions class============

package com.att.hcmlink.hcmlinkruleengine;

//import java.lang.Integer.parseInt;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Calendar;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import java.text.ParseException;
import java.sql.Timestamp;
import java.time.Instant;

/**
 * This class was automatically generated by the data modeler tool.
 */

@org.kie.api.definition.type.Expires("10ms")
public class Functions implements java.io.Serializable {

static final long serialVersionUID = 1L;

public Functions() {
}

public static String ConditionMatcherFunction(String lhs, String rhs,
String result, String originalVal) {
if (lhs.equals(rhs))
return result;
else
return originalVal;
}

public static String splitString(String str, String startPos, String endPos) {
return str.substring(Integer.parseInt(startPos),
Integer.parseInt(endPos));
}

public static String changeDateFormat(String sourceFormat,
String destinationFormat, String dateVal) throws ParseException {

DateFormat inputDateFormat = new SimpleDateFormat(sourceFormat);
inputDateFormat.setLenient(false);
DateFormat outputDateFormat = new SimpleDateFormat(destinationFormat);
Date date = null;
String returnDate = dateVal;

date = inputDateFormat.parse(dateVal);
returnDate = outputDateFormat.format(date);

return returnDate;

}
}

=================SourceData.java===========================



package com.att.hcmlink.hcmlinkruleengine;

/**
 * This class was automatically generated by the data modeler tool.
 */

@org.kie.api.definition.type.Expires("10ms")
public class SourceData implements java.io.Serializable {

static final long serialVersionUID = 1L;

@org.kie.api.definition.type.Label("columnName")
private java.lang.String columnName;
@org.kie.api.definition.type.Label("columnValue")
private java.lang.String columnValue;
@org.kie.api.definition.type.Label("ruleName")
private java.lang.String ruleName;
@org.kie.api.definition.type.Label(value = "ruleParam")
private java.util.Map<java.lang.String, java.lang.String> ruleParam;
@org.kie.api.definition.type.Label(value = "row")
private java.util.Map<java.lang.String, java.lang.String> row;
@org.kie.api.definition.type.Label(value = "output")
private java.util.Map<java.lang.String, java.lang.String> output;

@org.kie.api.definition.type.Label("destColumnName")
private java.lang.String destColumnName;

@org.kie.api.definition.type.Label("destColumnPosition")
private java.lang.Integer destColumnPosition;

@org.kie.api.definition.type.Label("destColumnValue")
private java.lang.String destColumnValue;

@org.kie.api.definition.type.Label("rownum")
private java.lang.Integer rownum;

@org.kie.api.definition.type.Label("executionPhase")
private java.lang.Integer executionPhase;

@org.kie.api.definition.type.Label("status")
private java.lang.String status;

@org.kie.api.definition.type.Label("exMsg")
private java.lang.String exMsg;

}
with all getters, setters, constructor, equals, hashcode, and tostring method





Toshiya Kobayashi

unread,
May 18, 2021, 2:18:36 AM5/18/21
to Drools Usage

Hi,

Do you enable GC logging? (-verbose:gc -XX:+PrintGCDetails) Do you see frequent Full GC?

If the heap is exhausted, GC would likely cause the slowness so you would eventually need to solve heap/object problem but it's good to have GC logging anyway.

Then, as you say "I am getting heap space issue", do you capture the heap dump while the heap gets exhausted? You can analyze the heap with tools like Eclipse Memory Analyzer (MAT). Then please let us know the major objects which occupy the heap ("Histogram" view).

Thanks,
Toshiya

2021年5月18日火曜日 4:52:25 UTC+9 sam.d...@gmail.com:

Samaresh Deyashi

unread,
May 18, 2021, 8:55:33 AM5/18/21
to Drools Usage
Hi Toshiya,

I am getting Heap Space error due to this issue:

02:32:50.511 [http-nio-8088-exec-3] ERROR o.a.c.c.C.[.[.[.[.a.h.JerseyConfiguration] - Servlet.service() for servlet [com.att.hcmlink.JerseyConfiguration] in context with path [] threw exception [org.glassfish.jersey.server.ContainerException: java.lang.OutOfMemoryError] with root cause
java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3236)
at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118)
at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:153)
at org.kie.server.common.rest.KieServerHttpRequest$3.run(KieServerHttpRequest.java:765)
at org.kie.server.common.rest.KieServerHttpRequest$3.run(KieServerHttpRequest.java:758)
at org.kie.server.common.rest.KieServerHttpRequest$Operation.call(KieServerHttpRequest.java:313)
at org.kie.server.common.rest.KieServerHttpRequest.copy(KieServerHttpRequest.java:769)
at org.kie.server.common.rest.KieServerHttpRequest.responseBody(KieServerHttpRequest.java:1349)
at org.kie.server.common.rest.KieServerHttpRequest.access$2100(KieServerHttpRequest.java:117)
at org.kie.server.common.rest.KieServerHttpRequest$5.body(KieServerHttpRequest.java:1315)
at org.kie.server.client.impl.AbstractKieServicesClientImpl.makeHttpPostRequestAndCreateServiceResponse(AbstractKieServicesClientImpl.java:286)
at org.kie.server.client.impl.AbstractKieServicesClientImpl.makeHttpPostRequestAndCreateServiceResponse(AbstractKieServicesClientImpl.java:264)
at org.kie.server.client.impl.RuleServicesClientImpl.executeCommandsWithResults(RuleServicesClientImpl.java:66)

Thanks,
Sam

Samaresh Deyashi

unread,
May 18, 2021, 8:59:45 AM5/18/21
to Drools Usage

Hi Toshiya,

Also, I have noticed GC log. There is no Major Garbage Collection. But there are many minor GC happened.

Toshiya Kobayashi

unread,
May 19, 2021, 2:05:13 AM5/19/21
to Drools Usage
The stacktrace looks interesting.

~~~
java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3236)
at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118)
at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:153)
at org.kie.server.common.rest.KieServerHttpRequest$3.run(KieServerHttpRequest.java:765)
at org.kie.server.common.rest.KieServerHttpRequest$3.run(KieServerHttpRequest.java:758)
at org.kie.server.common.rest.KieServerHttpRequest$Operation.call(KieServerHttpRequest.java:313)
at org.kie.server.common.rest.KieServerHttpRequest.copy(KieServerHttpRequest.java:769)
at org.kie.server.common.rest.KieServerHttpRequest.responseBody(KieServerHttpRequest.java:1349)
at org.kie.server.common.rest.KieServerHttpRequest.access$2100(KieServerHttpRequest.java:117)
at org.kie.server.common.rest.KieServerHttpRequest$5.body(KieServerHttpRequest.java:1315)
at org.kie.server.client.impl.AbstractKieServicesClientImpl.makeHttpPostRequestAndCreateServiceResponse(AbstractKieServicesClientImpl.java:286)
at org.kie.server.client.impl.AbstractKieServicesClientImpl.makeHttpPostRequestAndCreateServiceResponse(AbstractKieServicesClientImpl.java:264)
at org.kie.server.client.impl.RuleServicesClientImpl.executeCommandsWithResults(RuleServicesClientImpl.java:66)
~~~

You face OutOfMemoryError on kie-server-client application side? Or do you deploy both kie-server.war and kie-server-client application on the same application server?

Also let us know the heap dump analysis -> You can analyze the heap with tools like Eclipse Memory Analyzer (MAT). Then please let us know the major objects which occupy the heap ("Histogram" view).

Thanks,
Toshiya


2021年5月18日火曜日 21:59:45 UTC+9 sam.d...@gmail.com:

Samaresh Deyashi

unread,
Jun 17, 2021, 9:54:59 AM6/17/21
to Drools Usage
Hi Toshiya,

After you mentioned about  the client application , I have checked the client application logs and you are right. Above mentioned heap space is occurring because of client application memory leak. We have fixed all memory leak present in client application. It is already 1 month and I have tested with many big files. I am not facing this heap space error anymore.

Thanks for your help!

Toshiya Kobayashi

unread,
Jun 17, 2021, 11:06:40 PM6/17/21
to Drools Usage
I'm glad to hear that you solved the issue :)

Cheers,
Toshiya

2021年6月17日木曜日 22:54:59 UTC+9 sam.d...@gmail.com:
Reply all
Reply to author
Forward
0 new messages