2012-06-29 5 views
6

私は10000000時間のハッシュマップにキーを関連付けます。なぜクロージャー内のJavaネイティブHashMapがゆっくり実行されるのですか?

import java.util.HashMap; 

public class TestMap { 
    public static void main(String[] args) { 
     HashMap<Integer, Integer> mp = new HashMap<Integer, Integer>(); 
     long start = System.currentTimeMillis(); 
     for (int i = 0; i < 10000000; i++) { 
      mp.put(1, 1); 
     } 
     long end = System.currentTimeMillis(); 
     System.out.println("Elapsed time: " + (end - start) + " msecs"); 
    } 
} 


$ javac TestMap.java && java -cp . TestMap 
Elapsed time: 38 msecs 

をそして私はREPLでのClojureからJavaを呼び出す:ここでは、Javaコードと出力です

user=> (import java.util.HashMap) 
java.util.HashMap 
user=> (def mp (HashMap.)) 
#'user/mp 
user=> (time (dotimes [n 10000000] (.put mp 1 1))) 
"Elapsed time: 10024.797 msecs" 
nil 

両方のコードが同じことを行うが、Clojureのバージョンはexstreamly遅い実行されます!

問題が何ですか?

+1

BTWこれはClojureでどのように3行だけであり(読みやすく)簡単ですか? – erturne

答えて

13

型ヒントを追加するには優れている:

user> (import 'java.util.HashMap) 
java.util.HashMap 
user> (def mp (HashMap.)) 
#'user/mp 
user> (time (dotimes [n 10000000] (.put mp 1 1))) 
"Elapsed time: 13932.248126 msecs" 
nil 
user> (time (dotimes [n 10000000] (.put ^HashMap mp 1 1))) 
"Elapsed time: 117.915992 msecs" 
nil 
+0

タイプヒントの詳細については、http://clojure.org/java_interop#Java%20Interop-Type%20Hints –

9

このようなパフォーマンスの問題が発生する最初の手順は、反射の警告をオンにして削除することです。

(set! *warn-on-reflection* true) 

また、ループと再帰のオーバーヘッドが最も低くなります。

0

また、宣言

HashMap<Integer, Integer> mp = new HashMap<Integer, Integer>(10000000); 

にHashMapのサイズを宣言すると、Javaコードの速度を向上させることができ、私はそれが(私はまた、REPLのための方法であると思いますそれを知らない)、メモリスペースを予約することは可能ですか?

+0

を参照してください。これは当てはまりますが、このケースでは大きな違いはありません。実際の問題は反射です – mikera

関連する問題