ClojureScript地图查找速度慢

icy*_*com 4 clojure clojurescript

我有一张简单的地图:

(def my-map
  {[1 2 3] 1
   [1 2 4] 5
   [3 4 2] 3
   [4 5 3] 3
   [5 2 5] 6
   [9 2 1] 5
   [8 3 1] 6})
Run Code Online (Sandbox Code Playgroud)

我用来执行查找.然而,这表现得相当糟糕:

(time (doseq [x (range 500)]
        (my-map [1 2 8])))

"Elapsed time: 170 msecs"
Run Code Online (Sandbox Code Playgroud)

在同一台机器上,Clojure可以在大约236毫秒内完成500,000,或者大约700倍.虽然Clojure比ClojureScript更快并不出人意料,但我很困惑为什么ClojureScript会慢得多.

关于如何在ClojureScript中以高效且可读的方式制作简单的多值查找地图的任何想法?我知道做一堆ifs而不是使用矢量键解决方案肯定会更快,但我正在寻找一些更具可读性/可维护性的东西.

只是为了更新更多信息.以上是在Firefox中完成的,因此比V8慢.下列:

(def my-map2
  (into cljs.core.PersistentHashMap/EMPTY
        {[1 2 3] 1
         [1 2 4] 5
         [3 4 2] 3
         [4 5 3] 3
         [5 2 5] 6
         [9 2 1] 5
         [8 3 1] 6}))

(defn p1 []
  (let [v [1 2 8]]
    (dotimes [_ 5]
      (time (dotimes [_ 500000]
              (get my-map2 v))))))
Run Code Online (Sandbox Code Playgroud)

得到:

"Elapsed time: 3295 msecs"

"Elapsed time: 3246 msecs"

"Elapsed time: 3113 msecs"

"Elapsed time: 3107 msecs"

"Elapsed time: 3121 msecs"
Run Code Online (Sandbox Code Playgroud)

在Chromium版本25.0.1364.160 Ubuntu 13.04(25.0.1364.160-0ubuntu3).所以在ClojureScript中,Clojure的速度仍然比Clojure快13倍,但这比之前要好得多.另请注意,我是在浏览器repl中直接运行它.

dno*_*len 7

在我的机器上运行你的高级编译的确切示例需要大约14毫秒的1.7ghz Macbook Air运行一个相对较新的源自源码的v8.

为了确保我们对我们认为我们正在进行基准测试的基准测试,最好写下这样的事情:

(let [v [1 2 8]]
  (dotimes [_ 5]
    (time
      (dotimes [_ 500000]
        (get my-map v)))))
Run Code Online (Sandbox Code Playgroud)

在我的机器上,Clojure JVM在机器上需要大约70ms.ClojureScript在大约3600ms左右运行,因此大约慢50倍.为什么?这是因为我们默认使用PersistentArrayMap,在使用复杂键定义小哈希映射时Clojure不会这样做.

如果我们这样定义my-map会发生什么:

(def my-map
  (into cljs.core.PersistentHashMap/Empty
    [[1 2 3] 1
     [1 2 4] 5
     [3 4 2] 3
     [4 5 3] 3
     [5 2 5] 6
     [9 2 1] 5
     [8 3 1] 6]))
Run Code Online (Sandbox Code Playgroud)

然后基准测试需要大约170毫秒,这与Clojure JVM相差无几.

所以Clojure实现了很多优化,我们尚未实现这些优化.我仍然会说,对于惯用的Clojure代码,我认为在V8等高度优化的JavaScript引擎上,我们所希望的最好是Clojure JVM的2-10倍.