ClojureScript映射查找慢 [英] ClojureScript map lookup slow

查看:145
本文介绍了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})

但是,这样执行效果相当不好:

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

已用时间:170 msecs

在同一台机器上,Clojure可以做大约236毫秒的500,000,或者大约700x。虽然Clojure的速度比ClojureScript快,但是我很困惑为什么ClojureScript会慢得多。



任何关于我如何做一个简单的多线程的想法,在ClojureScript中以可读的方式有效和有价值的查找映射?我知道做一堆如果而不是使用一个向量键解决方案肯定会更快,但我看的是一些更可读/可维护的。 p>

只是要更新更多信息。上面是在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))))))

提供:

 已用时间:3295 msecs

已用时间:3246 msecs

已用时间:3113 msecs

已用时间:3107 msecs

Chromium 25.0.1364.160 Ubuntu 13.04(25.0.1364.160-0ubuntu3)中的已用时间:3121毫秒



< 。所以仍然是ClojureScript比Clojure慢13倍,但是这比以前好多了。注意,我直接在浏览器复制中运行。

解决方案

在我的机器上运行高级编译的精确示例需要〜 14ms在我的1.7ghz Macbook Air上运行一个相对较新的源自v8。



为了确保我们的基准测试,我们认为我们的基准,最好写东西像这样:

 (let [v [1 2 8]] 
(dotimes [_ 5]
(time
(dotimes [_ 500000]
(get my-map v)))))

在我的机器上,这需要〜70ms的机器上的Clojure JVM。 ClojureScript在〜3600ms左右运行,所以大约慢了50X。为什么?这是因为我们默认使用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]))

然后需要〜170ms,这不是离Clojure JVM那么远。



因此,Clojure实现的许多优化我们还没有实现。仍然我会说,对于惯用的Clojure代码,我认为最好的,我们可以希望对高度调整的JavaScript引擎,如V8是2-10X的Clojure JVM ..


I have a simple map:

(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})

that I use for performing lookups. This performs rather poorly, however:

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

"Elapsed time: 170 msecs"

On the same machine, Clojure can do 500,000 in about 236 msecs, or about 700x faster. While it's not unexpected for Clojure to be faster than ClojureScript, I'm confused why ClojureScript would be so much slower.

Any ideas about how I could make a simple multi-valued lookup map as above efficiently and in a readable manner in ClojureScript? I know doing a bunch of ifs instead of using a vector-key solution would certainly work faster, but I'm looking at something that's somewhat more readable / maintainable.

Just to update with more information. The above was done in Firefox, so thus slower than compared to V8. The following:

(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))))))

gives:

"Elapsed time: 3295 msecs"

"Elapsed time: 3246 msecs"

"Elapsed time: 3113 msecs"

"Elapsed time: 3107 msecs"

"Elapsed time: 3121 msecs"

in Chromium Version 25.0.1364.160 Ubuntu 13.04 (25.0.1364.160-0ubuntu3). So still about 13x times slower in ClojureScript than Clojure, but that's much better than what it was before. Note also that I'm running this directly in browser repl.

解决方案

On my machine running your exact example with advanced compilation takes ~14ms on my 1.7ghz Macbook Air running a relatively recent v8 built from source.

To make sure we're benchmarking what we think we're benchmarking it's best to write something like this:

(let [v [1 2 8]]
  (dotimes [_ 5]
    (time
      (dotimes [_ 500000]
        (get my-map v)))))

On my machine this takes ~70ms on machine for Clojure JVM. ClojureScript runs this around ~3600ms, so about 50X slower. Why? It's because we default to PersistentArrayMap where Clojure does not when defining small hash maps with complex keys.

What happens if we define my-map like this instead:

(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]))

The benchmark then takes ~170ms, which isn't so far off from Clojure JVM.

So there's definitely plenty of optimizations that Clojure implements that we haven't gotten around to yet. Still I'd say that for idiomatic Clojure code I think the best we can hope for on highly tuned JavaScript engines like V8 is 2-10X of Clojure JVM..

这篇关于ClojureScript映射查找慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆