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

欢迎!请参阅关于页面了解有关此页面如何工作的更多信息。

+9
Clojure

最近在进行性能工作时,我发现将操作展开为单独的assoc调用比使用多个键(在我的特定应用程序中大约为10%)要快得多。Zachary Tellman随后指出,clojure.core根本不会在相对少数的键的情况下展开assoc操作。

我们已经简化了其他通过apply调用的性能关键函数,例如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 RAM)上运行,使用Ubuntu 12.04和Java 8的最新版本。附上cpuinfounamejava -version输出。

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

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

关于这个补丁还有一个悬而未决的问题:我们应该将这些调用展开到何种程度?update(在1.7 alphas中展开)展开为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 需要在语法引用之前很好地定义,所以我让它定义两次,一次慢一点,一次快一点。我会上传包含 arglists 的补丁。每个新 arity 是否都需要 arglist?还是现有的 arglists 够用?(我很担心对 arglists 元数据的理解并不完全可靠)关于 assoc 的现有测试非常有限。我树中有一些生成性测试,因为这似乎比为所有不同的 arity 编写案例更有趣。如果它有用,我可以贴出来,但这可能有些过度了。

0

评论者: michaelblume

这就是我提到的测试补丁,比我记忆中的还要夸张

0

评论者: michaelblume

好的,这是代码和测试。

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

0

评论者: alexmiller

现有的参数列表很好——它只是为了文档目的而覆盖了生成的参数列表。

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

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

0

评论者: michaelblume

更新补丁以应用到 master 分支

0

评论者: alexmiller

这仍然需要对不同计数频率进行评估。根据一些非常快速的检查,传入两个 kv 足够常见,以至于很重要。传入三个则很少见,以此类推。但我想从运行一些东西中得到一些大致的频率概念。我认为当前的展开做得太多了(可能 2-3 个 kv 就足够了)。

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