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

欢迎!请查看关于页面了解此功能的更多信息。

+9
Clojure

最近在进行性能工作时,我发现将unroll应用于单个assoc调用比使用多个键(在我的特定应用程序中为10%)快得多。然后,Zachary Tellman指出,clojure.core根本不对assoc进行unroll,即使是少量键的情况。

我们已经对通过apply调用的其他关键性能功能进行了unroll,例如update https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L5914,但assoc(我认为它在很多应用程序和库的临界路径上),可能从这一点受益。

我尚未为这个问题开发补丁,但我进行了一些独立的基准测试工作

https://github.com/yeller/unrolling-assoc-benchmarks

基准测试结果

代码: https://github.com/yeller/unrolling-assoc-benchmarks/blob/master/src/bench_assoc_unrolling.clj

| |1 |2 |3 |4 |
| :-- | :-- | :-- | :-- | :-- |
| 空数组映射(未展开) | 23ns | 93ns | 156ns | 224ns |
| 空数组映射(展开assoc) | N/A | 51ns | 80ns | 110ns |
| | | | | |
| 20个元素的持久性映射(未展开) | 190ns | 313ns | 551ns | 651ns |
| 20个元素的持久性映射(展开assoc) | N/A | 250ns | 433ns | 524ns |
| | | | | |
| 记录(未展开) | 12ns | 72ns | 105ns | 182ns |
| 记录(展开assoc) | N/A | 21ns | 28ns | 41ns |

每个测量都是在单独的JVM中进行的,以避免JIT路径依赖。

基准测试是在一台普通的服务器(8个CPU,32GB内存)上运行的,使用ubuntu 12.04和一个Java 8的最新版本。附上cpuinfounamejava -version的输出。

启用了相对标准的JVM生产标志,并小心地禁用了leiningen的启动时间优化(这会禁用许多JIT优化)。

通过克隆存储库并运行script/bench来运行基准测试。

关于这个补丁有一个悬而未决的问题:我们应该展开这些调用的多少?update(在1.7 alpha中进行了展开)展开到3个参数。添加更多展开并不困难,但这会影响assoc的可读性。

补丁: CLJ-1656-v5.patch

25 答案

0

评论者:alexmiller

是的,内联是通过 var 调用实现的。

0

评论者:tcrayford

Michael,

那个组只是应用了您的补丁的 clojure master 上传版本,与之前以相同的方式构建(您应该可以检出仓库并复制)。

0

评论者:alexmiller

补丁 CLJ-1656-v5.patch 似乎并没有对旧的 assoc 版本(在 core.clj 约 179 行附近)做任何事情?

新的版本需要具有 arglists 以及其他类似的内容。我不太确定那里宏/私有变量。您试过利用 RT.assocN() 与矢量一起使用吗?

测试套件中存在针对 assoc 和 N 对的应用的测试吗?

0

评论者:michaelblume

clojure.core 中的依赖关系导致 assoc 需要在 syntax-quoting 之前很好地定义,所以我只是让它在慢速和快速状态下都定义了两遍。我将提交一个包含 arglists 的补丁。每增加一个新参数是否都需要 arglist,还是现有的 arglists 足够?(我担心我并不完全清楚 arglists 元数据的用途)目前对 assoc 的现有测试非常缺乏。我在我的树中有一个生成性测试,因为这似乎比为所有不同的参数编写案例更有趣。如果它看起来有用,它可能有点过度。

0

评论者:michaelblume

这就是我之前提到的测试补丁,它比我记得的还要过度

0

评论者:michaelblume

好了,代码和测试。

: 这也检查了在 varargs 情况下,assoc! 是否接收到了偶数的 kvs,这是 assoc 的行为。测试验证了 assoc 和 assoc! 在奇数参数数量时都会抛出异常。

0

评论者:alexmiller

现有的 arglist 没问题,它只是覆盖了为文档目的生成的那个。

你尝试过 RT.assocN()的相关内容吗?

我认为我还有一个问题:人们实际上这样做足够多次以至于这很重要吗? :)

0

评论者:michaelblume

更新补丁,使其适用于 master。

0

评论者:alexmiller

这仍然需要对不同计数的频率进行评估。根据一些很简单的检查,传递两个 kvs 已经足够常见从而值得注意。传递三个的频率远低,以此类推。但我很乐意从执行一些操作中得到对频率的初步了解。我认为当前的展开太多(2到3个kvs可能是足够的)。

0
参考:https://clojure.atlassian.net/browse/CLJ-1656 (由 tcrayford 报告)
...