我们可以对 {{simple-ident?}}、{{qualified-ident?}}、{{simple-symbol?}}、{{qualified-symbol?}}、{{simple-keyword?}} 和 {{qualified-keyword?}} 函数进行一些优化。
可以进行两种不同的优化。
在 {{boolean}} 使用的地方(即 {{qualified-}} 函数),我们可以用 {{some?}} 来实现更快的执行
(boolean (and (symbol? x) (namespace x) true))
可以转换为简单形式
(and (symbol? x) (some? (namespace x)))
现在只关注 V8,对于
(simple-benchmark [x 'a/b f #(qualified-symbol? x)] (f) 100000000)
减去基础成本
(simple-benchmark [x 'a/b f (fn [] x)] (f) 100000000)
得到速度提升 1.74。
既然我们知道在应用 {{namespace}} 时我们在处理关键词或符号,我们可以进一步使用 {{(.-ns x)}}。
仅此一项就会带来 2.21 的速度提升,当与之前的优化组合
(and (symbol? x) (some? (.-ns x)))
时,我们会看到接近无限的速度提升(该操作实际上变得免费,所需时间与基线相同)。
请注意,我们可能可以使用由谓词引起的类型推断以及一个新的宏来替换 {{namespace}},该宏会输出 {{.-ns}},但 CLJS-2866 目前取决于在一个 {{if}} 中查看测试,而上述表达式则导致带有短路 {{&&}} 的优化 {{js*}} 输出。
这些优化会是好的,因为这些函数经常用于基于规范的生成代码测试中,这里性能可能是一个问题。
我们在 {{cljs.predicates-test}} 中为这些函数设置了测试覆盖率。
以下是为 {{qualified-symbol?}} 发出的当前 JavaScript 代码
function cljs$core$qualified_symbol_QMARK_(x) {
return cljs.core.boolean$(
(function() {
var and__8540__auto__ = x instanceof cljs.core.Symbol;
if (and__8540__auto__) {
var and__8540__auto____$1 = cljs.core.namespace(x);
if (cljs.core.truth_(and__8540__auto____$1)) {
return true;
} else {
return and__8540__auto____$1;
}
} else {
return and__8540__auto__;
}
})()
);
}
以下是修订后的结果
function cljs$user$qualified_symbol_QMARK_(x) {
return x instanceof cljs.core.Symbol && !(x.ns == null);
}
(此修订实现的紧凑性意味着可能通过 Closure 进一步内联,以实现更多针对整个程序优化的速度提升。)