为什么get-in慢于线程获取?

时间:2016-04-22 18:37:48

标签: clojure

我在调整一些对性能敏感的代码时遇到了这个问题:

user> (use 'criterium.core)
nil
user> (def n (into {} (for [i (range 20000) :let [k (keyword (str i))]] [k {k k}])))
#'user/n
user> (quick-bench (-> n :1 :1))
WARNING: Final GC required 32.5115186521176 % of runtime
Evaluation count : 15509754 in 6 samples of 2584959 calls.
Execution time mean : 36.256135 ns
Execution time std-deviation : 1.076403 ns
Execution time lower quantile : 35.120871 ns ( 2.5%)
Execution time upper quantile : 37.470993 ns (97.5%)
               Overhead used : 1.755171 ns
nil
user> (quick-bench (get-in n [:1 :1]))
WARNING: Final GC required 33.11057826481865 % of runtime
Evaluation count : 7681728 in 6 samples of 1280288 calls.
Execution time mean : 81.023429 ns
Execution time std-deviation : 3.244516 ns
Execution time lower quantile : 78.220643 ns ( 2.5%)
Execution time upper quantile : 85.906898 ns (97.5%)
               Overhead used : 1.755171 ns
nil

对我而言,get-in的速度是get的{​​{1}}的两倍,因为get-in似乎被定义为对此类事物的更好抽象,这是不直观的。

有没有人知道为什么会出现这种情况(技术上和哲学上)?

1 个答案:

答案 0 :(得分:8)

嵌套地图在Clojure程序中非常常用。这是一件好事。但有时可以通过展开来改进嵌套地图操作,例如assoc-inget-in。就生成的字节代码而言,(get :a (get :b (get :c (get :d m)))(get-in m [:d :c :b :a])不同。后面的字节代码导致执行时间更短。

请注意,Clojure有一些与此相关的待处理补丁http://dev.clojure.org/jira/browse/CLJ-1656