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

欢迎!请查看关于页面以获取更多的信息。

+9
Clojure

最近在进行性能工作时,我发现将关联展开成单个关联调用比使用多个键要快得多(对于我特定的应用来说,要快10%)。Zachary Tellman随后指出,clojure.core根本不会展开关联,即使是非常少的键数量。

我们已展开其他通过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路径依赖性。

基准测试是在使用ubuntu 12.04和Java 8的最新版本的商品服务器(8个CPU,32GB RAM)上运行的,并附带了cpuinfounamejava -version输出。

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

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

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

补丁: CLJ-1656-v5.patch

25个答案

0

评论者:alexmiller

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

0

评论者:tcrayford

迈克尔,

那个组只是将你的补丁应用在clojure master的版本上传,用相同的方式构建,你应该能够检出仓库并复制。

0

评论者:alexmiller

补丁CLJ-1656-v5.patch看起来并没有在core.clj中的旧版assoc(大约在第179行)上做任何事?

新版本需要arglists和其他类似的东西。我不确定里面的宏/private变量。你尝试过用vector利用RT.assocN()吗?

测试框架中是否存在针对assoc的N对参数的现有测试?

0

评论者:michaelblume

clojure.core中的依赖使得assoc需要在语法引号之前被很好地定义,所以我让它两次定义,一次慢一次快。我将发布包含arglists的补丁。每个新的arity都需要一个arglist吗,或者现有的arglists足够?(我害怕对arglists元数据不是很确定)对assoc的现有测试实在是不多。我在我的树中有生成性测试,因为它似乎比为所有不同的arity编写用例更有趣。如果有用,我可以发布,可能有点过度了。

0

评论者:michaelblume

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

0
by

评论者:michaelblume

那里的代码和测试。

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

0
by

评论者:alexmiller

现有的参数列表没有问题 - 它只是为了文档目的覆盖了自动生成的参数列表。

你试过 RT.assocN() 的任何东西吗?

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

0
by

评论者:michaelblume

更新补丁以应用于 master

0
by

评论者:alexmiller

这仍然需要对不同计数的频率进行评估。根据一些非常快速的检查,传递两个 kvs 已经足够常见到影响到了。传递三个则远不如常见,等等。但我非常希望看到一些关于运行这些事情的大致的频率估算。我认为当前的展开过多(约为 2-3 kvs 就足够了)。

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