我们可以对 {{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 进一步内联以获得更多的程序优化速度提升。)