`${refer} 隐藏在 `${require}`,`${use}` 和 `${refer-clojure} 用例中,并且在将符号/变量映射从另一个命名空间复制到当前命名空间的主体工作中效率不高。
方法:一些可以进行优化的改进
- 直接进入命名空间映射,避免创建过滤的中间映射表(ns-publics)
- 使用transients构建引用到refer的映射表
- 不是分别cas每个新的引用,而是构建所有变化的映射表,然后cas
- 对于`(:require :only ...)`情况 - 不是遍历所有引用的变量并寻找匹配,只需遍历包含的变量并查询每个变量
毫无疑问,还有更多巨大的变化(如不可变命名空间)全部如何工作,可能会进一步提高性能,但我尽量使变更范围保持在较小规模。
虽然单个refer性能有所降低(`refer clojure.core`大约降低50%,`:only`使用降低90%),但refer只是更广泛的require加载时间中一个小组成部分,因此在实践中改善是有限的。
性能
| 新repl中的表达式 | 1.7.0-beta3 | 1.7.0-beta3+补丁 |
| :-- | :-- | :-- | :-- |
| (in-ns 'foo) (clojure.core/refer 'clojure.core) | 2.65 ms | 0.994 ms |
| (in-ns 'bar) (clojure.core/refer 'clojure.core :only '(link: inc dec)) | 1.04 ms | 0.113 ms |
| (use 'criterium.core) | 0.877 ms | 0.762 ms |
| (require '(link: clojure.core.async :refer (>!!
补丁:clj-1730-2.patch
筛选笔记
补丁似乎正确,但我们应考虑
- 使用`${if}`而不是`${when}`使用不自然的语法,使得分支难以阅读
- 不自然的`${if}`缩进(两个分支在同一行)难以阅读
- 我认为`找不到(未知)`不应该是${IllegalAccessError},但原始代码已经这样做,所以...
- 围绕swap的乐观并发循环永远不会放弃,这是否可以?