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 alpha中被展开)展开为3个参数。添加更多的展开并不困难,但这会影响assoc的可读性。

补丁:CLJ-1656-v5.patch

25 答案

0

评论者:alexmiller

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

0

评论者:tcrayford

迈克尔,

该组只是应用了补丁的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 中提供一个补丁。每个新的arity都需要arglist吗,还是现有的arglists足够?(我担心我对arglists元数据的了解不太清楚)对于 assoc 的现有测试还是有点令人讨厌的缺乏。我在我的树中有生成性测试,因为这似乎比为所有不同的arity编写案例更有趣。如果它看起来有用,我可以发表它,但它可能有点过度了。

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 提出)
...