Les performances de la compilation vs interprété javascript dans java7 / Rhino

J'ai un problème avec la performance de Rhino moteur javascript Java7, peu de temps - mon script (qui analyse et compile des textes) s'exécute dans le navigateur Chrome autour de 50 à 100 fois plus rapide que la même en Java7 Rhino moteur de script.

J'ai essayé de trouver le moyen d'améliorer la situation et ont constaté que la Rhino prend en charge la compilation des scripts. J'ai essayé de le faire avec mes scripts et en fait ne vois aucune amélioration. Enfin - j'ai fini avec un mannequin d'essai de suite où je ne vois aucune différence de performance entre compilé et interprété versions. S'il vous plaît laissez-moi savoir ce que j'avais fait de mal.

Remarque: certaines sources mentionnent que le Rhino moteur tourne script compilé environ 1,6 plus lent que le "même" code écrit directement en Java. Vous ne savez pas si la "compilation de script" utilisé dans cet exemple est le même que celui qui est censé là.

De Test de la classe java est ci-dessous et exemple de résultat que j'obtiens sur ma machine ...

Résultats

 À l'aide d'com.sun.script.javascript.RhinoScriptEngine@c50443 ... 
temps: 886ms, chars: 38890, somme: 2046720 
temps: 760ms, chars: 38890, somme: 2046720 
temps: 725ms, chars: 38890, somme: 2046720 
temps: 765ms, chars: 38890, somme: 2046720 
temps: 742ms, chars: 38890, somme: 2046720 
... 3918ms 


À l'aide d'com.sun.script.javascript.RhinoCompiledScript@b5c292 @ com.sun.script.javascript.RhinoScriptEngine@f92ab0 ... 
temps: 813ms, chars: 38890, somme: 2046720 
temps: 805ms, chars: 38890, somme: 2046720 
temps: 812ms, chars: 38890, somme: 2046720 
temps: 834ms, chars: 38890, somme: 2046720 
temps: 807ms, chars: 38890, somme: 2046720 
... 4101ms 

mise à Jour après le commentaire de Anon-Micro:

Après avoir décroché l'appel du JavaScript eval() et de compiler() dans la classe de test en ...

import sun.org.mozilla.javascript.internal.Context;
try {
    Context cx = Context.enter();

    cx.setOptimizationLevel(9);
    cx.setLanguageVersion(170);

    ...
}
finally {
    Context.exit();
}

résultat changé signigicantly - à partir de la moyenne de 1,8 (dans la nouvelle version de la classe de test) s à ~150msec. Cependant instance de la doTest() la fonction extraite de ScriptEngine chargé par (CompiledScript = Compilable.compile()).eval(Bindings) -> Bindings.get("doTest") toujours dit que c'est sun.org.mozilla.javascript.internal.InterpretedFunction et ses performances sont légèrement inférieures (environ 10%) que la version de JS chargé de la pré-compilé en bytecode (par Rhino 1.7r4) - donc, je ne suis toujours pas sûr de ce qui se passe réellement derrière la scène.

1800ms - ScriptEngine.eval(), Optimization Level = default(-1?)
1758ms - CompiledScript, Optimization Level = default(-1?)
 165ms - ScriptEngine.eval(), Optimization Level = 9
 132ms - CompiledScript, Optimization Level = 9
 116ms - compiled by Rhino 1.7r4 into bytecode class

PS: le soleil.org.mozilla.le javascript.interne.Contexte au sein de soleil interne du package air d'être un drôle de conception de moi - l '"intérieur" désigne cette classe est présumé ne pas être utilisé par les développeurs et à cet effet, il n'est pas "certifié" façon de manipuler le niveau d'optimisation de la JS évaluateur dans Java 7.

de la classe de Test (mise à jour, doTestCompiled est chargé à partir externes *.classe)

import javax.script.Bindings;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.Invocable;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.SimpleScriptContext;
import sun.org.mozilla.javascript.internal.Context;
import sun.org.mozilla.javascript.internal.Scriptable;
import sun.org.mozilla.javascript.internal.Function;
public class RhinoPerfTest4 {
final static ScriptEngineManager scm = new ScriptEngineManager();
final static String TEST_SCRIPT1 =
"function doTest() {\n"
+ "    var scale = 5000, i, a = [], str, l, sum = 0,\n"
+ "        start = (new Date()).getTime(), end;\n"
+ "    for( i = 0; i < scale; i++ )\n"
+ "        a.push(\"\" + i);\n"
+ "    str = a.join(\"\");\n"
+ "    l = str.length;\n"
+ "    for( i = 0; i < l; i++ ) {\n"
+ "        var c = str.charCodeAt(i);\n"
+ "        if( c > 0)\n"
+ "            sum += c;\n"
+ "    }\n"
+ "    end = (new Date()).getTime();\n"
+ "\n"
+ "    //print(\" time: \" + (end - start) "
+ "          + \"ms, chars: \" + l "
+ "          + \", sum: \" + sum + \"\\n\");\n"
+ "}\n";
final static String TEST_SCRIPT2 =
"function doTest() {\n"
+ "    var a = [], i;\n"
+ "    for( i = 0; i < 500; i++ ) a.push(1);\n"
+ "}\n";
static class TestSet {
public int nCycles;
public String script;
public TestSet(int nCycles, String script) {
this.nCycles = nCycles;
this.script = script;
}
}
static TestSet set1 = new TestSet(5, TEST_SCRIPT1);
static TestSet set2 = new TestSet(500, TEST_SCRIPT2);
public static void main(String[] args) throws Exception {
ScriptEngine se;
int i;
long ts, te;
TestSet set = set1;
Object noArgs[] = new Object[]{};
try {
org.mozilla.javascript.Context mctx = org.mozilla.javascript.Context.enter();
se = scm.getEngineByExtension("js");
doTestCompiled doTestPreCompiled = new doTestCompiled();
org.mozilla.javascript.Scriptable scope = mctx.initStandardObjects();
doTestPreCompiled.call(mctx, scope, scope, null);
org.mozilla.javascript.Function doTest = 
(org.mozilla.javascript.Function)scope.get("doTest", null);
for( int nHotSpot = 0; nHotSpot < 5; nHotSpot++ ) {
if( nHotSpot > 0 )
Thread.sleep(500);
ts = System.currentTimeMillis();
for( i = 0; i < set.nCycles; i++ ) {
doTest.call(mctx, scope, null, null);
}
te = System.currentTimeMillis();
System.out.println("  " + nHotSpot + ": " + (te - ts) + "ms");
}
}
finally {
org.mozilla.javascript.Context.exit();
}
for( int nOpt = 0; nOpt < 2; nOpt++ ) {
if( nOpt > 0 )
Thread.sleep(500);
Context cx = null;
try {
System.out.println("Cycle: " + nOpt);
cx = Context.enter();
if( nOpt > 0 ) {
System.out.println("OptLevel: " + 9);
cx.setOptimizationLevel(9);
cx.setLanguageVersion(170);
}
se = scm.getEngineByExtension("js");
se.eval(set.script);
System.out.println("\nRunning via " + se + " ... ");
Invocable invocable = (Invocable) se;
for( int nHotSpot = 0; nHotSpot < 5; nHotSpot++ ) {
if( nHotSpot > 0 )
Thread.sleep(500);
ts = System.currentTimeMillis();
for( i = 0; i < set.nCycles; i++ ) {
invocable.invokeFunction("doTest", noArgs);
}
te = System.currentTimeMillis();
System.out.println("  " + nHotSpot + ": " + (te - ts) + "ms");
}
se = scm.getEngineByExtension("js");
Compilable cse = (Compilable) se;
CompiledScript cs = cse.compile(set.script/* + "(doTest())"*/);
Scriptable scope = cx.initStandardObjects();
ScriptContext scriptContext = new SimpleScriptContext();
Bindings vars = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE);
cs.eval(vars);
Object odoTest = scriptContext.getAttribute("doTest");
Function doTest = (Function) vars.get("doTest");
System.out.println("\nRunning via " + cs + " @ " + se + " ... ");
for( int nHotSpot = 0; nHotSpot < 5; nHotSpot++ ) {
if( nHotSpot > 0 )
Thread.sleep(500);
ts = System.currentTimeMillis();
for( i = 0; i < set.nCycles; i++ ) {
doTest.call(cx, scope, null, noArgs);
}
te = System.currentTimeMillis();
System.out.println("  " + nHotSpot + ": " + (te - ts) + "ms");
}
}
finally {
if( cx != null )
Context.exit();
}
}
}
}

OriginalL'auteur Xtra Coder | 2013-01-26