2012-06-29 34 views
6

我將密鑰與散列映射關聯10000000次。下面是Java代碼和輸出:爲什麼clojure中的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調用java從Clojure的:

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

順便說一句,在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

還可以增加Java代碼的速度與聲明HashMap的大小在聲明

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

我想這是一個也REPL的方式(我做不知道它),是否有可能保留內存空間?

+0

這是事實,但在這種情況下並沒有多大區別 - 真正的問題是反射 – mikera