I'm interpreting a same script in both Groovy and Beanshell.
Groovy takes a very long time(26 mins 25 secs), while Beanshell takes only 20 secs.
I'm very astonished by the difference and I don't understand why, Is Beanshell is better? Am I using Groovy is wrong?
Groovy code:
public void calcule_irg(double salaire) throws Throwable{
Binding binding = new Binding();
binding.setVariable("MNT_943", 0);
String script="double formule_irg(Double salaireSoumis) {\n" +
" int salaire = salaireSoumis.intValue();\n" +
" salaire = salaire / 10 * 10;\n" +
" \n" +
" Double impots = 0.0;\n" +
" \n" +
" if (salaire >= 15000 && salaire <= 22500) {\n" +
" impots = ((salaire - 10000) * 0.2) - 1000.0;\n" +
" } else if (salaire > 22500 && salaire <= 30000) {\n" +
" impots = ((salaire - 10000) * 0.2);\n" +
" impots = impots - (impots * 0.4);\n" +
" } else if (salaire >= 30001 && salaire <= 120000) {\n" +
" impots = 2500 + ((salaire - 30000) * 0.3);\n" +
" } else if (salaire >= 120001) {\n" +
" impots = 29500 + ((salaire - 120000) * 0.35);\n" +
" } else {\n" +
" impots = 0.0;\n" +
" }\n" +
" \n" +
" return impots.intValue();\n" +
"} \n" +
"\n" +
"MNT_943 = formule_irg("+salaire+") ;\n";
GroovyShell shell = new GroovyShell(binding);
shell.evaluate(script);
Double value =(Double) shell.getVariable("MNT_943");
}
Beanshell code:
public void calcule_irg(double salaire) throws EvalError {
Interpreter i = new Interpreter(); // Construct an interpreter
// Eval a statement and get the result
String script="double formule_irg(Double salaireSoumis) {\n" +
" int salaire = salaireSoumis.intValue();\n" +
" salaire = salaire / 10 * 10;\n" +
" \n" +
" Double impots = 0.0;\n" +
" \n" +
" if (salaire >= 15000 && salaire <= 22500) {\n" +
" impots = ((salaire - 10000) * 0.2) - 1000.0;\n" +
" } else if (salaire > 22500 && salaire <= 30000) {\n" +
" impots = ((salaire - 10000) * 0.2);\n" +
" impots = impots - (impots * 0.4);\n" +
" } else if (salaire >= 30001 && salaire <= 120000) {\n" +
" impots = 2500 + ((salaire - 30000) * 0.3);\n" +
" } else if (salaire >= 120001) {\n" +
" impots = 29500 + ((salaire - 120000) * 0.35);\n" +
" } else {\n" +
" impots = 0.0;\n" +
" }\n" +
" \n" +
" return impots.intValue();\n" +
"} \n" +
"\n" +
"MNT_943 = formule_irg("+salaire+") ;\n";
i.eval(script);
}
Main:
public static void main(String[] args) throws Throwable{
Groovy g=new Groovy();// The function mentioned below is defined in a class named Groovy
Beanshell s=new Beanshell();// The function mentioned below is defined in a class named Beanshell
String fileName = "c://salaires100K.txt";
//read file into stream, try-with-resources
try (Stream<String> stream = Files.lines(Paths.get(fileName))) {//This file contains 100'000 Salary, means 100'000 lines
stream.forEach( n->{
try {
g.calcule_irg(Double.parseDouble(n));//I use either this
//s.calcule_irg(Double.parseDouble(n));//Or this
} catch (Throwable ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
You better use Groovy 2 compiled statically feature
Since version 2, Groovy can also be compiled statically, offering type inference, and performance near that of Java
In your case for each iteration call same script outside of the loop:
compiledScript = ((Compilable) scriptEngine).compile(script);
compiledScript.eval(binding);
Also script can be marked as CompileStatic, for example:
import groovy.transform.CompileStatic
@CompileStatic
int squarePlusOne(int num) {
num * num + 1
}
assert squarePlusOne(3) == 10