欢迎!请参阅关于页面了解如何使用本服务。
最近在进行性能工作时,我发现将关联展开为单个关联调用比使用多个键要快得多(在我的特定应用中大约快了10%)。Zachary Tellman随后指出,clojure.core根本不会对关联进行展开,即使是相对较低数量的键。
我们已将其他性能关键函数解耦,例如通过apply调用,例如update https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L5914,但assoc(我认为它在许多应用和库中的关键路径上),可能会从中受益。
apply
update
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 || 空数组映射(展开关联) | N/A | 51ns | 80ns | 110ns | | | | | | || 20个元素的持久性哈希映射(未展开) | 190ns | 313ns | 551ns | 651ns || 20个元素的持久性哈希映射(展开关联) | N/A | 250ns | 433ns | 524ns | | | | | | || 记录(未展开) | 12ns | 72ns | 105ns | 182ns || 记录(展开关联) | N/A | 21ns | 28ns | 41ns |
每个测量都是在独立的JVM中进行的,以避免JIT路径依赖。
基准测试在一台普通服务器上运行(8个CPU,32G内存),使用Ubuntu 12.04 和最新的Java 8版本。附上cpuinfo,uname和java -version的输出。
cpuinfo
uname
java -version
启用了相对标准的JVM生产标志,并小心禁用了leiningen的启动时间优化(这禁用了许多JIT优化)。
可以通过克隆仓库并运行script/bench来运行基准测试。
script/bench
关于此补丁有一个悬而未决的问题:我们应该将这此调用展开多远?update(在第1.7 alpha中展开)展开为3个参数。增加更多解耦并不困难,但这会影响关联的可读性。
补丁:CLJ-1656-v5.patch
评论者:alexmiller
是的,内联通过var调用来实现。
评论者:tcrayford
Michael,
那个组仅仅是应用了您的补丁的上传版本 clojure master,按照以前完全相同的方式构建的,您应该可以检出仓库并复刻。
补丁 CLJ-1656-v5.patch 在老版本的 assoc (在 core.clj 约179行) 似乎没有做任何事情?
新的版本需要 arglists 和其他类似的东西。我不确定那里的宏/私有变量,您尝试过利用 RT.assocN() 与一个向量一起用吗?
测试套件中存在针对具有 N 对的 assoc 的现有测试吗?
评论者:michaelblume
clojure.core中的依赖关系使得 assoc 必须在语法引用之前被正确定义,所以我就让它被定义了两次,一次慢,一次快。我将提供一个带有 arglists 的补丁。是否需要为每个新 arities 提供一个 arglist,或者是现有的 arglists 足够?(我担心我对 arglists 元数据的了解不够充分) 对于 assoc 的现有测试非常不足。我在我的代码树中有一个生成性测试,因为它似乎比为所有不同的 arities 写用例更有趣。如果有用,我可以发给你,但可能有些过度。
这就是我提到的测试补丁,比我记忆中还要多
那里,代码和测试。
这也检查在 varargs 情况下,assoc! 接收到偶数个 kvs,这是 assoc 的行为。测试验证了assoc和 assoc! 在奇数参数计数时都会抛出异常。
现有的参数列表是好的——它只是为了文档目的覆盖了生成的那个。
你尝试过任何 RT.assocN() 的东西吗?
我想另一个问题是,人们是否真正做了很多这样的事情,以至于它很重要? :)
更新补丁以应用于 master
这还需要对不同计数的频率进行评估。根据一些非常快速的检查,传递两个 kv 非常常见,足以引起注意。传递三个就很少见,以此类推。但我想看到一些从运行一些内容中得到的关于频率的大致想法。我认为当前的展开太多了(2-3 kv 可能足够)。