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

Michael:

那个小组只是将你的补丁应用于 clojure master 的上传版本,以与之前相同的方式构建(你应该能够检出存储库并复制)。

0

评论者:alexmiller

补丁 CLJ-1656-v5.patch 好像没有在 core.clj 的旧版本 assoc (大约在第 179 行) 中做任何事情?

新的一个需要 arglists 以及其他类似的东西。我对此处宏/私有变量也不是很确定。你尝试过使用 RT.assocN() 和向量一起利用了吗?

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

0

评论者:michaelblume

clojure.core 中的依赖关系使得 assoc 需要在语法引号之前就被很好地定义,所以我让它被定义了两次,一次慢一点,一次快一点。我会提供一个带有 arglists 的补丁。对于每个新的秩,需要 arglist 吗?或者现有的 arglists 已足够?(我害怕我对 arglists 元数据的了解不是100%)关于 assoc 的现有测试令人讨厌地缺失。我在我的树中有生成测试,因为这似乎比为各种秩编写用例更有趣。如果它似乎有用,它可能会过于冗余。

0

评论者:michaelblume

这是我之前提到的测试补丁,比我记忆中的更加冗余

0

评论者:michaelblume

那里有代码和测试。

这也检查了在varargs情况下无论传入多少kvs,assoc!都会通过偶数个参数,这是assoc的行为。测试验证了assoc和assoc!在奇数参数的情况下都会抛出异常。

0

评论者:alexmiller

现有的arglist很好,只是为了文档目的覆盖了生成的arglist。

你尝试过RT.assocN()相关的东西吗?

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

0

评论者:michaelblume

更新补丁以应用到master

0

评论者:alexmiller

这仍然需要对不同计数的频率进行评估。根据一些非常快速的检查,传入两个kvs足够常见,足以产生影响。传入三个就更不常见了,依此类推。但我想看到一些从运行一些东西中得到的粗略频率概念。我认为当前的展平(unrolling)太多了(2-3个kvs可能就足够了)。

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