请分享您的想法,参与2024年Clojure状态调查:

欢迎!请查阅关于页面,了解更多有关如何使用本网站的信息。

+1
Clojure
已关闭

'zipmap'构造一个不使用transient映射的map,而使用transient可以改进性能。

方法:使用内部transient映射加上键值迭代器。持久性映射如之前一样返回。定义也被移动,以便它位于#'_transient'下面。

性能

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

| 表达式 | 1.7.0-beta3 | +patch | |
| :-- | :-- | :-- | :-- | :-- |
| (zipmap xs xs) | 4.50毫秒 | 2.12毫秒 | 大映射
| (zipmap ys ys) | 2.75微秒 | 2.07微秒 | 小映射

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

审核:Alex Miller

已注解关闭: 在1.10.2-rc1中修复

13 答案

0

评论者:aaron

为什么旧实现被保留并注释掉?如果我们打算迁移到新的实现,旧的一个应该被删除。

0

评论者:michalmarczyk

如问题描述中所述,之前附上的补丁遵循into的非transient启用定义模式,其在core.clj中留下的定义前面有#_ - 我不确定这是否在所有情况下都期望的。

这是一个新的补丁,去掉了旧实现。

0

评论人:jafingerhut

感谢您更新补丁,Michal。很抱歉提出这样一个小问题,但您能否为更新的补丁使用一个不同的名称?我知道JIRA可以处理同名多个附件,但我的预筛选代码还不够聪明,这可能导致在讨论补丁时产生混淆。

0

评论者:michalmarczyk

谢谢您提前提醒,Andy!我已经使用新名称重新附着了新的补丁。

0

评论人:jafingerhut

在Michal的更新补丁添加后,我会假设性地将审批状态从“不完整”改回“无”,解决标记工单为“不完整”的原因。

0

评论者:aaron

这个补丁看起来不错,应用良好。我们还需要运行额外的测试来验证这个补丁是否提供了我们预期的改进。此外,有没有某种讨论开始了这个工单?这里的上下文不多。

0

评论者:michalmarczyk

嗨 Aaron,

感谢您调查此事!

据我所观察,这个更改大大提高了{{zipmap}}在大型地图中的性能。对于小型地图,只有一点改进。以下是两个基本的Criterium基准({{transient-zipmap}}在REPL中定义为补丁中所见)

`
;;; 大型地图
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 ms(2.5%)
执行时间上限:4.494120 ms(97.5%)
nil
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 ms(2.5%)
执行时间上限:3.025812 ms(97.5%)

在60个样本中发现了2个异常值(3.3333%)

low-severe	 2 (3.3333 %)

异常值差异:25.4675% 异常值使得方差适中高估
nil

;;; 小型地图
user=> (def ys (range 16))

'user/ys

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

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

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

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

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

显然,只要瞬态满足它们的合约,语义就会得到保留。

我想可能我没有为这个启动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实现仍在内部不使用transient映射。为什么从没应用过?

0
_由:alexmiller_发表的评论

这里提出了多种方法,尚未确定共识方法。需要一些专注时间来缩小范围,这还不是优先事项。
0
参考: https://clojure.atlassian.net/browse/CLJ-1005(由michalmarczyk报告)
...