OutOfMemoryError using JEP

56 views
Skip to first unread message

LUIS ALBERTO RIVERA RIERA

unread,
Nov 5, 2013, 10:43:09 AM11/5/13
to jep-...@googlegroups.com
Hi,
This is Luis, I am working for a Credit Card company and we are using your demo product(Jep java) to evaluate client’s scores and actually we are in a Test stage but we are facing java.lang.OutOfMemoryError problems when we are running a set of 25000 clients.
The application consist in a RPG program that call a Evaluate.jar where we have implemented the logic to evaluate expressions. 
All the clients have 200 expression to evaluate so finally we have a loop for a total = 50000000 repetitions( 25000clients*200expression = 50000000 ).

The count loop reached = 245000 and we got java.lang.OutOfMemoryError.

I would like that you guys can give support with this problem.

This is the code that i am using :
package ec.com.diners.evaluator;
import java.text.DecimalFormat;
import java.util.Locale;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.singularsys.jep.Jep;
import com.singularsys.jep.ParseException;
import com.singularsys.jep.configurableparser.StandardConfigurableParser;


public abstract class WrapperEvaluator{
public static String verifyExpression(String expression) throws Exception{
try{

       Jep jep = new Jep(new StandardConfigurableParser());
String[] parms = expression.split("#");
String formula = parms[0];
formula.intern();
for (int i = 1; i < parms.length; i++) {
       if (parms[i] != null) {
           String[] paramList = parms[i].split("=");
           String nombreVariable = paramList[0];
           nombreVariable.intern();
           String valorVariable = paramList[1];
           if(valorVariable.length() > 14){
  char indicadorNegativo; 
  String parteEntera  =  valorVariable.substring(0,9);
  String parteDecimal = valorVariable.substring(9,15);
  indicadorNegativo = parteDecimal.charAt(5);
  if(!Character.isDigit(indicadorNegativo)){
parteDecimal = valorVariable.substring(9,14);
jep.addVariable(nombreVariable,Double.parseDouble(parteEntera+"."+parteDecimal)*-1);
}else
jep.addVariable(nombreVariable,Double.parseDouble(parteEntera+"."+parteDecimal));
}

}
}
   jep.parse(formula);
Object var = jep.evaluate(); 
Locale.setDefault(Locale.US);
   DecimalFormat num = new DecimalFormat("#########.000000");
   jep=null;    
   return num.format(var);
}
catch( ParseException ex){
Logger logger = LoggerFactory.getLogger(WrapperEvaluator.class);
logger.error(ex.getStackTrace().toString());
return ex.getMessage();
}
finally{
Logger logger = LoggerFactory.getLogger(WrapperEvaluator.class);
StringBuffer message = new StringBuffer(100);
long heapMaxSize = Runtime.getRuntime().maxMemory();
long heapSize = Runtime.getRuntime().totalMemory();
long heapFreeSize = Runtime.getRuntime().freeMemory();
message.append(" RESUMEN **** HeapMaxSize: " + heapMaxSize + " HeapSize: " + heapSize + " HeapFreeSize :" + heapFreeSize);
logger.debug(message.toString());
if(heapSize == heapMaxSize){
System.gc();
logger.debug("Llamando al GC: Actual heapFreeSize: "+ heapFreeSize);
}
}
}

}


Thanks in advance.

Richard Morris

unread,
Nov 5, 2013, 6:04:32 PM11/5/13
to jep-...@googlegroups.com
Hi Luis,

Thats quite a nice test for the system, one of the largest I've seen. A few thoughts.

You are creating a new Jep instance each time verifyExpression() is called. This takes some memory and time it will be better to reuse the same Jep instance. So change

public abstract class WrapperEvaluator{
public static String verifyExpression(String expression) throws Exception{
try{
        Jep jep = new Jep(new StandardConfigurableParser());
                ...
                }
        }
 }

to

public abstract class WrapperEvaluator{
Jep jep = new Jep(new StandardConfigurableParser());

public static String verifyExpression(String expression) throws Exception{
try{
                ...
                }
        }
 }

Keeping the same jep instance has some implications, mainly the variables will be kept. You may want to call
       jep.getVariableTable().clear();
or

        jep.getVariableTable().remove("x");


The other thing I note is the use of String.intern. I don't know much about this method but reading 
seems to indicate problems with garbage collection.

Further investigation might involve static memory analysis to see which classes are using up the space. Some sample expressions might help.

Richard
Reply all
Reply to author
Forward
0 new messages