2015-11-08 10 views
15

「JavaScript」ScriptEngine(JSR-223)を幅広く使用するJavaプログラム(JDK 7u80を使用してコンパイルされています)があります。私は、Java 7ランタイム環境(JRE 7u80)と比較して、Java 8ランタイム環境(JRE 8u65)で実行されたときに自分のプログラムが非常に遅く実行されることに気付きました。Java 8 ScriptEngineの主なパフォーマンスに関する問題Java 7との比較

私はこの問題を示すために、一緒に次SSCCEを配置し、同じWindows PC上でJava 7およびJava 8の下でそれを実行した:

import javax.script.*; 

public class SSCCE { 
    public SSCCE() { 
    ScriptEngineManager sem = new ScriptEngineManager(); 
    ScriptEngine js = sem.getEngineByName("JavaScript"); 
    long t = 0; 
    int i = 0; 

    String gJs = "function ip2long(ip) {"; 
    gJs += "var aIP = ip.split(\".\");"; 
    gJs += "return (aIP[0] * Math.pow(256, 3)) + (aIP[1] * Math.pow(256, 2)) + (aIP[2] * 256) + (aIP[3] * 1);"; 
    gJs += "}"; 
    gJs += "function long2ip(l) {"; 
    gJs += "if (!isNaN(l) && ((l >= 0) || (l <= Math.pow(2, 32)))) {"; 
    gJs += "return Math.floor(l/Math.pow(256, 3)) + \".\" +"; 
    gJs += "Math.floor((l % Math.pow(256, 3))/Math.pow(256, 2)) + \".\" +"; 
    gJs += "Math.floor(((l % Math.pow(256, 3)) % Math.pow(256, 2))/Math.pow(256, 1)) + \".\" +"; 
    gJs += "Math.floor((((l % Math.pow(256, 3)) % Math.pow(256, 2)) % Math.pow(256, 1))/Math.pow(256, 0));"; 
    gJs += "}"; 
    gJs += "return null;"; 
    gJs += "}"; 

    try { 
     js.eval(gJs); 
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
    } 

    System.out.println("Warming Up..."); 

    t = System.nanoTime(); 

    for (i = 0; i < 4097; i++) { 
     try { 
     String sJs = "var ip = \"192.0.2.0\";"; 
     sJs += "var nip = long2ip(ip2long(ip, " + i + "));"; 
     js.eval(sJs); 
     } 
     catch (Exception e) { 
     e.printStackTrace(); 
     } 
    } 

    System.out.println("Starting..."); 

    t = System.nanoTime(); 

    for (i = 0; i < 4097; i++) { 
     try { 
     String sJs = "var ip = \"192.0.2.0\";"; 
     sJs += "var nip = long2ip(ip2long(ip, " + i + "));"; 
     js.eval(sJs); 
     } 
     catch (Exception e) { 
     e.printStackTrace(); 
     } 
    } 

    System.out.println("Elapsed Time: " + (System.nanoTime() - t)/1000000000.0f); 
    } 

    public static void main(String[] args) { 
    new SSCCE(); 
    } 
} 

JavaScriptがにIPアドレスを変換する関数で構成されてい長さを追加して数字を追加し、それをIPアドレスに戻します。これは4096回繰り返されます。

私は、Java 7とJava 8の間に次のような結果を見ています:

D:\Scripts>java7 SSCCE 
Warming Up... 
Starting... 
Elapsed Time: 0.5856594 

D:\Scripts>java8 SSCCE 
Warming Up... 
Starting... 
Elapsed Time: 4.6862915 

私は、Java 8に関連したパフォーマンスのバグとしてこれを引き上げるべきか?

更新済み:タイミングループの前にすべてのコードパスが初期化されていることを確認するウォームアップフェーズを含める。

+2

の定数の使用方法おそらくウォーミングアップ段階を含まなかったため、結果を再現できません。 – Tunaki

+0

これは、Java 7とJava 8のパフォーマンスの違いについて何も言及していない質問と重複していますか?それはマイクロベンチマークを行う方法を述べた記事です。その投稿を正しく読んだら、2回目のループを行うべきですが、2回目にタイミングを合わせるだけです。 – chrixm

+2

正しいベンチマークを行うためにJMHを調べることをお勧めします。ウォームアップ段階を自動的に含み、間違ったことの測定を避けるライブラリです。 NahsornがRhinoよりも読み込みに時間がかかるため、あなたが得ている違いがあります。 – Tunaki

答えて

3

Java 8は、コンパイルされたスクリプトの方法を使用すると、毎回ソースコードを再評価しないように、JavaScriptエンジンを改善します。 evalメソッドでは、jdk8で使用されるHashormエンジンはjdk7で使用されるRhinoよりも低速ですが、より安全です。

は、文字列対のStringBufferを優先し、Math.pow(2、32)とMath.pow(256、3)の値あなたはスピードを探しているならば...

ユアーズ

+0

すべてのコメントと提案に感謝します。ユーザーがJavaScriptを提供しているために可能でない領域(私の使用例は、ユーザーがJavaScriptをブロックで使用できるテンプレートツールです)では、私は、固定スレッドプールのXスレッドを使用してテンプレートを並列処理するスレッドモジュール。 – chrixm

関連する問題