【问题标题】:Why is get-in slower than threading through gets?为什么 get-in 比线程通过 get 慢?
【发布时间】:2016-08-16 12:21:04
【问题描述】:

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

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 的速度比通过gets 的速度慢两倍以上,这对我来说是不直观的,因为get-in 似乎被定义为这类事情的更好抽象。

有没有人知道为什么会这样(技术上和哲学上)?

【问题讨论】:

  • 如果您查看这两个函数的源代码,您会发现get-in 中进行了一些递归,允许它梳理嵌套结构。我猜这就是额外开销的来源。
  • 我只能猜测 get-in 是一个更“通用”的功能,而且开销更大。在我的电脑上,它并没有那么糟糕,分别为 31 ns 和 57 ns。

标签: clojure


【解决方案1】:

嵌套映射在 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

【讨论】:

  • 我认为递归函数调用不是问题,而是需要分配的许多向量。
猜你喜欢
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
  • 1970-01-01
  • 2014-07-21
  • 2021-01-15
  • 2015-07-09
  • 2016-10-29
  • 1970-01-01
相关资源
最近更新 更多