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 |
| :-- | :-- | :-- | :-- | :-- |
| 空数组映射(未 unroll) | 23ns | 93ns | 156ns | 224ns |
| 空数组映射(unroll assoc) | N/A | 51ns | 80ns | 110ns |
| | | | | |
| 20 个元素的持久性映射哈希表(未 unroll) | 190ns | 313ns | 551ns | 651ns |
| 20 个元素的持久性映射哈希表(unroll assoc) | N/A | 250ns | 433ns | 524ns |
| | | | | |
| 记录(未 unroll) | 12ns | 72ns | 105ns | 182ns |
| 记录(unroll assoc) | N/A | 21ns | 28ns | 41ns |

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

基准测试在一个普通服务器(8 核心处理器,32gb 内存)上运行,使用 Ubuntu 12.04 和 Java 8 的最新版本。附上了 cpuinfounamejava -version 输出。

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

可以通过克隆仓库并运行 script/bench 来运行基准测试

针对此补丁有一个未解决的问题:我们应该将调用 unroll 多远?update(它在 1.7 alpha 中已 unroll)已 unroll 为 3 个参数。添加更多的 unroll 并不难,但这会影响 assoc 的可读性。

补丁: CLJ-1656-v5.patch

25 答案

0
by

评论者:alexmiller

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

0
by

评论者:tcrayford

迈克尔,

该小组只是应用了您的补丁的clojure master版本的上传版本,构建方式和以前一样(您应该能够检出仓库并进行复制)。

0
by

评论者:alexmiller

补丁CLJ-1656-v5.patch似乎对旧版本的assoc (在core.clj的第179行附近) 没有做什么?

新的需要具有arglists和其他类似的东西。我不确定那里的宏/私有变量。你是否尝试用vector利用RT.assocN()?

测试套件中是否有对具有N对的assoc进行测试的现有测试?

0
by

评论者:michaelblume

clojure.core中的依赖关系是这样的,assoc需要在语法引用之前定义得很好,所以我只是让它定义两次,一次较慢,一次较快。我将提供一个带有arglists的补丁。每个新参数是否都需要arglist,或者现有arglists就足够了?(我担心我不是100%清楚arglists元数据的用途)assoc的现有测试很令人厌烦。我在我的树中有生成测试,因为这似乎比为所有不同的参数编写案例更有趣。如果它看起来有用,它可能有点过于冗余,但我可以发布如果看起来有用。

0
by

评论者:michaelblume

这就是我提到的测试补丁,比我想的还要冗余。

0

评论者:michaelblume

那里,代码和测试。

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

0

评论者:alexmiller

现有的参数列表是好的,它只是为了文档目的覆盖了生成的那个。

你尝试过任何 RT.assocN() 的事情吗?

我想问的另一个问题是,人们是否真的经常这么做以至于这很重要? :)

0

评论者:michaelblume

更新补丁以适用于 master

0

评论者:alexmiller

这仍然需要评估不同数量的频率。根据一些非常快速的检查,传递两个 kvs 足够常见到足以重要。传递三个则远不常见,依此类推。但我很想知道通过运行一些东西的大致频率。我认为当前的展开太多了(2-3 kvs 很可能是足够的)。

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