2024 Clojure 状态调查! 中分享您的想法。

欢迎!请参阅 关于 页面获取有关如何使用本站的更多信息。

+2
记录和类型
重新标记

在我们的 TMD 路径之一(来自 mastodon),我们使用 defrecords 扩大数据集的大小。令人惊讶的是,考虑到其他性能案例正在做的一切,实现 IReduceInit 使得计时大大增加。


tech.v3.dataset.reductions-test> (require '[criterium.core :as crit])
nil
tech.v3.dataset.reductions-test> (defrecord YMC [year-month ^long count]
  ;; clojure.lang.IReduceInit
  ;; (reduce [this rfn init]
  ;;   (let [init (reduced-> rfn init
  ;;                  (clojure.lang.MapEntry/create :year-month year-month)
  ;;                  (clojure.lang.MapEntry/create :count count))]
  ;;     (if (and __extmap (not (reduced? init)))
  ;;       (reduce rfn init __extmap)
  ;;       init)))
  )
tech.v3.dataset.reductions_test.YMC
tech.v3.dataset.reductions-test> (let [yc (YMC. :a 1)]
                                   (crit/quick-bench (reduce (fn [acc v] v) nil yc)))
Evaluation count : 6729522 in 6 samples of 1121587 calls.
             Execution time mean : 87.375170 ns
    Execution time std-deviation : 0.173728 ns
   Execution time lower quantile : 87.104982 ns ( 2.5%)
   Execution time upper quantile : 87.550708 ns (97.5%)
                   Overhead used : 2.017589 ns
nil
tech.v3.dataset.reductions-test> (defrecord YMC [year-month ^long count]
   clojure.lang.IReduceInit
   (reduce [this rfn init]
     (let [init (reduced-> rfn init
                    (clojure.lang.MapEntry/create :year-month year-month)
                    (clojure.lang.MapEntry/create :count count))]
       (if (and __extmap (not (reduced? init)))
         (reduce rfn init __extmap)
         init)))
  )
tech.v3.dataset.reductions_test.YMC
tech.v3.dataset.reductions-test> (let [yc (YMC. :a 1)]
                                   (crit/quick-bench (reduce (fn [acc v] v) nil yc)))
Evaluation count : 43415358 in 6 samples of 7235893 calls.
             Execution time mean : 11.775423 ns
    Execution time std-deviation : 0.197683 ns
   Execution time lower quantile : 11.594695 ns ( 2.5%)
   Execution time upper quantile : 12.079668 ns (97.5%)
                   Overhead used : 2.017589 ns
nil
tech.v3.dataset.reductions-test> (defmacro reduced->
  [rfn acc & data]
  (reduce (fn [expr next-val]
            `(let [val# ~expr]
               (if (reduced? val#)
                 val#
                 (~rfn val# ~next-val))))
          acc
          data))

#'tech.v3.dataset.reductions-test/reduced->
tech.v3.dataset.reductions-test> 

与其他成员讨论后,似乎在 __extmap 不为 nil 的情况下,值查找路径也可以进行优化(它使用 clojure.core/get 而不是直接的 getorDefault 调用。

2 个答案

0

被选中
 
最佳答案

这很有趣。我实际上在 1.12.0-alpha1 的其他 reduce 变化背景下考虑过这个问题,但我们没有证据表明这是一个问题。我明天将为这个问题创建一个工单。

by
非常有趣!我也花费了大量时间使用 ham-fisted 和 dtype-next 使 reduce 尽可能地快。我在几乎所有我能想到的情况下都对其进行了大量的剖析,并致力于一些详细的事情,例如确保 map 和 filter 操作(以及 transducers)尊重 map 函数或 filter 函数的运行时类型,这样您就可以构建原始类型操作的链,整个链将是原始类型,中间没有装箱。

一个奇特的巧合的研究。
+1
by
...