在2024年Clojure状态调查中分享您的想法!2024 State of Clojure Survey!

欢迎!有关如何操作的更多信息,请参阅关于页面。

+1投票
Clojure
已关闭

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

方法:内部使用transient映射,并使用键和值的迭代器。返回持久性映射与之前相同。定义也被移动,使其位于'`transient`'之下。

性能

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

| 表达式 | 1.7.0-beta3 | +补丁 | |
| :-- | :-- | :-- | :-- | :-- |
| (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毫秒(2.5%)
执行时间上四分位数:4.494120毫秒(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毫秒(2.5%)
执行时间上四分位数:3.025812毫秒(97.5%)

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

low-severe	 2 (3.3333 %)

异常值带来的方差:25.4675%,方差被异常值中度夸大了
nil

;;; 小图
用户=> (def ys (range 16))

'用户/ys

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

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

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

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

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

很明显,只要瞬时对象满足它们的契约,就可以保留语义。

我认为我可能没有启动一个ggroup线程来处理这个问题,抱歉。

0投票

评论由:jafingerhut 发布

修补程序0001-使用-zipmap中的瞬时映射.2.patch(2012年8月15日)无法在2014年9月3日提交Clojure的最新主分支后干净地应用。

我尚未检查此修补程序是否容易更新。有关更新修补程序的建议,请参阅“更新陈旧的修补”部分,网址为http://dev.clojure.org/display/community/Developing Patches

0投票
_由:michalmarczyk_发表的评论

谢谢,Andy。更新很容易 - 自动rebase。这里是更新后的修补程序。
0投票

评论由:gshayban发表

新修补程序使用clojure.lang.RT/iter,criterium显示在最佳案例中性能提升超过30%。可能分配更少,但我没有测量。与CLJ-1499(更好的迭代器)相关

0投票

评论由:justinspedding发表

4年后,核心命名空间中这个zipmap实现依旧没有使用瞬时映射。为什么从未应用这个?

0投票
_由:alexmiller_发表的评论

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