``` 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+patch |
| :-- | :-- | :-- | :-- |
| (in-ns 'foo) (clojure.core/refer 'clojure.core) | 2.65 毫秒 | 0.994 毫秒 |
| (in-ns 'bar) (clojure.core/refer 'clojure.core :only '(link: inc dec)) | 1.04 毫秒 | 0.113 毫秒 |
| (use 'criterium.core) | 0.877 毫秒 | 0.762 毫秒 |
| (require '(link: clojure.core.async :refer (>!! <!! chan close!))) | 3408 毫秒 | 3302 毫秒 |
补丁:clj-1730-2.patch
筛选注释
补丁看起来是正确的,但我们应该考虑
- 不使用 `` when '' 而是使用非习惯性的 `` if '',这使得分支难以阅读
- 非习惯性的 `` if '' 缩进(两个分支在一行上)难以阅读
- 我认为不应将未找到的情况视为 `` IllegalAccessError '',但原始代码已经是这样做的,所以 ...
- 围绕 `swap` 的乐观并发循环绝不会放弃,这样可以吗?