Planck Lazy Analysis Cache Loading
But, a significant portion of Planck initialization is time spent reading in the analysis cache for the ClojureScript runtime.
What is the analysis cache? It is essentially metadata about code that is generated by the ClojureScript compiler. Think AST, along with other ancillary stuff like docstrings. It is used, for example, to know information about the
Since it takes so long to load the analysis cache for
cljs.core, I tried a quick experiment, commenting out the code that loads this cache. Planck's startup time was cut nearly in half.
A surprising result is that, even without the
cljs.core analysis cache, the evaluation of certain forms like
(inc 3) or
(+ 1 2) works, while others like
(map inc [1 2 3]) fail. I suspect that the root cause for this is that the ClojureScript analyzer can locate and execute the code needed for macroexpansion without even consulting the analysis cache. (Things like
+ are functions and macros).
So, if the analysis cache is not needed for those forms, I thought it would be interesting to delay loading the cache, and to essentially fault it in only when needed. This would make use cases like
planck -e'(+ 1 2)'
even faster. One challenge, though, is that the
cljs.core analysis cache is just one portion of a larger map maintained by the compiler that holds all of the analysis caches for all of the loaded namespaces, and this gigantic map can be consulted (or revised) at any time by the compiler when it is doing its work.
cljs.core is essentially static, read-only. So, it is a candidate to be treated like a
delay, and pulled in only when necessary.
Enter lazy-map. This is a library by Artur Malabarba that essentially lets you defer the realization of values in a map. I took it, and put it into Planck. Instead of greedily loading in the
cljs.core analysis cache Transit data (already in use to make Replete faster), it makes use of
lazy-map to set up triggers that load this info on demand perchance the compiler touches it.
It works! On one box, executing
planck -e'(+ 7 (inc 3))'
drops from 247 ms to 155 ms, shaving off a hefty 37% from the startup time. And, this is getting closer to the 80-ms threshold where I suspect you can no longer perceive the startup latency.
This lazy loading has landed in Planck master and will appear in Planck 1.9.