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

欢迎!请访问关于页面以了解更多关于如何使用该工具的信息。

+1投票
Clojure
已关闭

'zipmap在构建映射时不使用transients,而使用transients可以提高性能。

方法:内部使用transient映射以及关键值迭代器。像以前一样返回持久映射。定义也进行了移动,使其位于'#transient'定义之下。

性能

(def xs (range 16384))
(def ys (range 16))

|表达式|1.7.0-beta3|+补丁|
| :-- | :-- | :-- | :-- | :-- |
|(zipmap xs xs)|4.50 ms|2.12 ms|大映射
|(zipmap ys ys)|2.75 us|2.07 us|小映射

补丁:CLJ-1005-zipmap-iterators.patch

审查者:Alex Miller

关闭的说明:更新修复在1.10.2-rc1中

13个答案

0投票

评论由:aaron发表

为什么保留旧的实现并将其注释掉?如果我们打算转向新的实现,应该删除旧的那个。

0投票

评论由:michalmarczyk发表

如票证描述所述,之前附带的补丁遵循以下模式:在 core.clj 中保留非瞬态启用定义 forefront 的前面一个 #_,我不确定这在所有情况下是否是期望的行为。

这里有一个新补丁,移除了旧的实现。

0投票

评论者:jafingerhut

Michal,感谢你更新了补丁。很抱歉提出这么小的问题,但你能给更新后的补丁起一个不同的名字吗?我知道 JIRA 可以处理同名的多个附件,但我的预筛选代码还不够聪明,这可能会在讨论补丁时导致混淆。

0投票

评论由:michalmarczyk发表

Andy,感谢你的提醒!我已经用新的名字重新附上新的补丁。

0投票

评论者:jafingerhut

在 Michal 的更新补丁添加后,擅自将审批状态从“不完整”改回“无”,解决了票证被标记为不完整的原因。

0投票

评论由:aaron发表

该补丁看起来很好,并且应用正常。我们是否应该运行额外的测试以验证此补丁是否提供了我们认为的改进。此外,是否有任何讨论引起了这个票证的讨论?这里没有太多上下文。

0投票

评论由:michalmarczyk发表

嗨 Aaron,

感谢你对此事的关注!

根据我观察到的,这个更改极大地提高了大型地图的 {{zipmap}} 时间。对于小型地图,有轻微的改进。以下是在补丁中定义的 REPL 的两个基本 Criterium 基准测试({{transient-zipmap}})

`
; 大型地图
user=> (def xs (range 16384))

'user/xs

user=> (last xs)
16383
user=> (c/bench (zipmap xs xs))
评估次数:13920次,其中60个样本为232个调用。

         Execution time mean : 4.329635 ms
Execution time std-deviation : 77.791989 us

执行时间下四分位数:4.215050 毫秒(2.5%)
执行时间上四分位数:4.494120 毫秒(97.5%)
null
user=> (c/bench (transient-zipmap xs xs))
评估次数:21180,在 60 个样本的 353 次调用中。

         Execution time mean : 2.818339 ms
Execution time std-deviation : 110.751493 us

执行时间下四分位数:2.618971 毫秒(2.5%)
执行时间上四分位数:3.025812 毫秒(97.5%)

在 60 个样本中找到 2 个异常值(3.3333%)

low-severe	 2 (3.3333 %)

异常值的方差:25.4675%,方差受到异常值的影响而适度膨胀
null

;; 小映射
user=> (def ys (range 16))

'user/ys

user=> (last ys)
15
user=> (c/bench (zipmap ys ys))
评估次数:16639020,在 60 个样本的 277317 次调用中。

         Execution time mean : 3.803683 us
Execution time std-deviation : 88.431220 ns

执行时间下四分位数:3.638146 微秒(2.5%)
执行时间上四分位数:3.935160 微秒(97.5%)
null
user=> (c/bench (transient-zipmap ys ys))
评估次数:18536880,在 60 个样本的 308948 次调用中。

         Execution time mean : 3.412992 us
Execution time std-deviation : 81.338284 ns

执行时间下四分位数:3.303888 微秒(2.5%)
执行时间上四分位数:3.545549 微秒(97.5%)
null
`

显然,只要瞬态满足其规范,语义就能得到保留。

我想我可能没有开始一个 ggroup 线程来处理这个,对不起。

0投票

评论者:jafingerhut

补丁 0001-Use-transient-map-in-zipmap.2.patch 日期为 2012 年 8 月 15 日,在 2014 年 9 月 3 日对 Clojure 进行了一些提交后,无法干净地应用于最新的 master。

我没有检查这个补丁是否容易更新。请参阅http://dev.clojure.org/display/community/Developing Patches中的“更新旧的补丁”部分,了解有关如何更新补丁的建议。

0投票
_评论者:michalmarczyk_

谢谢,Andy。更新非常直接——自动变基。以下是更新后的补丁。
0投票

评论者:gshayban

使用 clojure.lang.RT/iter 的新补丁,在最佳情况下可以看到 >30% 的性能提升。可能分配更少,但没有进行测量。CLJ-1499(更好的迭代器)相关

0投票

评论者:justinspedding

4 年后,核心命名空间中的这个 zipmap 实现仍然没有使用瞬态映射。为什么这个从未应用呢?

0投票
_评论者:alexmiller_

在此提出了多个方法,尚未确定共识方法。需要一些时间来聚焦并缩小范围,但现在还不是优先事项。
0投票
参考:https://clojure.atlassian.net/browse/CLJ-1005 (michalmarczyk 报告)
...