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

欢迎!请参阅关于页面以了解更多此网站的信息。

+4
Clojure

问题:当前select-keys使用conj来添加条目。如果映射是可编辑的,可以改用conj!以改进select-keys的性能。

此外,keyseq作为一个序列进行遍历,但也可以通过reduce进行遍历,这可能会更快。

方法1:使用transient映射和conj!,保持loop/recur
方法2:重新实现select-keys,用reduce代替loop/recur
方法3:将方法一和方法二结合起来

|所选键大小 | loop/recur | transient | reduce | transient + reduce |
| :-- | :-- | :-- | :-- | :-- | :-- |
|1 | 243 ns | 256 ns | 161 ns | 188 ns |
|7 | 1.1 ms | - | 885 ns | 454 ns |

在这些数字的基础上,选择了方法三。

注意:为了将select-keys用reduce实现,需要将其移动到reduce定义之后。这强制使用了(declare select-keys),因为它在reduce定义之前就被使用了。

补丁:(链接:https://dev.clojure.org/jira/secure/attachment/17392/0001-CLJ-1789-Use-transients-and-reduce-with-select-keys.patch 文件:0001-CLJ-1789-Use-transients-and-reduce-with-select-keys.patch)

3 个回答

0
_评论者:slipset_

标准的Clojure select-keys

 (bench (clojure.core/select-keys {:a "b" :c "d"} [:a]))
评估数量:246382440,在60次样本中,每次调用的次数为4106374。
             平均执行时间:243.245536 ns
    执行时间标准差:2.714803 ns
   下四分位数执行时间:238.473675 ns(2.5%)
   上四分位数执行时间:248.544255 ns(97.5%)
                   使用的开销:1.845047 ns


使用transient

(bench (select-keys {:a "b" :c "d"} [:a]))
评估数量:232727220,在60次样本中,每次调用的次数为3878787。
             平均执行时间:256.937568 ns
    执行时间标准差:10.025123 纳秒
   执行时间下四分位数:249.951872 纳秒(2.5%)
   执行时间上四分位数:276.251590 纳秒(97.5%)
                   使用的开销:1.845047 ns

在60个样本中发现5个异常值(8.3333%)
    轻重异常     3(5.0000%)
    轻度异常     2(3.3333%)
 异常值方差:25.4503% 异常值导致方差适度膨胀


减少后

(bench (select-keys {:a "b" :c "d"} [:a]))
评估次数:364807860次,来自60个样本中的6080131次调用。
             执行时间平均值:161.582833 纳秒
    执行时间标准差:2.212659 纳秒
   执行时间下四分位数:158.027524 纳秒(2.5%)
   执行时间上四分位数:167.673682 纳秒(97.5%)
                   使用的开销:1.845047 ns

在60个样本中发现3个异常值(5.0000%)
    轻重异常     3(5.0000%)
 异常值方差:1.6389% 异常值导致方差轻微膨胀

减少 + 瞬时

(bench (select-keys {:a "b" :c "d"} [:a]))
评估次数:318075720次,来自60个样本中的5301262次调用。
             执行时间平均值:188.656164 纳秒
    执行时间标准差:3.024952 纳秒
   执行时间下四分位数:183.867285 纳秒(2.5%)
   执行时间上四分位数:195.466784 纳秒(97.5%)
                   使用的开销:1.845047 ns

在60个样本中发现4个异常值(6.6667%)
    轻重异常     4(6.6667%)
 异常值方差:1.6389% 异常值导致方差轻微膨胀


在大尺寸映射/选择中

(bench (clojure.core/select-keys {:a "b" :c "d" :b "b" :d "d" :e "e" :f "f" :g "g"} [:a :c :b :d :e :f :g]))
评估次数:56147160次,来自60个样本中的935786次调用。
             执行时间平均值:1.104653 微秒
    执行时间标准差:36.366516 纳秒
   执行时间下四分位数:1.048257 微秒(2.5%)
   执行时间上四分位数:1.142031 微秒(97.5%)
                   使用的开销:1.845047 ns

在60个样本中发现5个异常值(8.3333%)
    轻重异常     4(6.6667%)
    轻度异常     1(1.6667%)
 异常值方差:19.0389% 异常值导致方差适度膨胀

减少

(bench (select-keys {:a "b" :c "d" :b "b" :d "d" :e "e" :f "f" :g "g"} [:a :c :b :d :e :f :g]))
评估次数:67723500次,来自60个样本中的1128725次调用。
             执行时间平均值:885.840664 纳秒
    执行时间标准差:11.503115 纳秒
   执行时间下四分位数:864.403495 纳秒(2.5%)
   执行时间上四分位数:905.721942 纳秒(97.5%)
                   使用的开销:1.845047 ns

瞬时 + 减少

(bench (select-keys {:a "b" :c "d" :b "b" :d "d" :e "e" :f "f" :g "g"} [:a :c :b :d :e :f :g]))
评估次数:134119380次,来自60个样本中的2235323次调用。
             执行时间平均值:454.587795 纳秒
    执行时间标准差:15.681611 纳秒
   执行时间下四分位数:439.822498 纳秒(2.5%)
   执行时间上四分位数:485.797378 纳秒(97.5%)
                   使用的开销:1.845047 ns

在60个样本中发现3个异常值(5.0000%)
    轻重异常     3(5.0000%)
 异常值方差:20.6393% 异常值导致方差适度膨胀


附上的补丁同时使用了瞬时和减少
0

由:alexmiller 提出

我认为提出的方法是好的。描述需要更好地反映考虑和选择的内容。

0
参考:[https://clojure.atlassian.net/browse/CLJ-1789](https://clojure.atlassian.net/browse/CLJ-1789)(由 alexmiller 提出)
...