嗨!
我阅读了关于如何在开发期间减少REPL启动时间的资料,并尝试将这些知识应用到使用Leiningen启动REPL(Alex在文章中展示了使用deps.edn这一实践)。
我的步骤
我覆盖了clojure.core/load变量,以追踪加载模块所花费的时间:
(alter-var-root #'clojure.core/load (fn [origin-fn]
(if (get (meta origin-fn) ::track-load?)
origin-fn
(vary-meta (fn [& args]
(let [start# (System/nanoTime)
ret# (apply origin-fn args)
elapsed-ms# (/ (double (- (System/nanoTime) start#)) 1000000.0)]
(newline)
(pr {:args (vec args)
:ms elapsed-ms#})
(newline)
ret#))
merge
{::track-load? true}))))
我发现加载核心Clojure部分花费时间大约为0.10-0.20毫秒,加载第三方库模块(例如cheshire)需要约200-400毫秒。
根据我的理解,减少REPL启动时间的主要思想是,如果clj模块未更改,则编译类文件优先于clj模块。因此,我们可以编译第三方库,并通过使用它们的编译后的类文件而不是解析它们的clj文件来获得好处。
我使用Leiningen的uberjar编译了所有Clojure文件(包括我的和库),并将包含编译后的类文件的文件夹添加到:checkout-deps-shares中,我猜这是一种将包含类文件的文件夹添加到类路径的方式。
:checkout-deps-shares [:source-paths :test-paths
~(fn [p] (str (:root p) "/target/uberjar/classes/*"))]
然后我重新启动了REPL,覆盖了clojure.core/load以追踪模块加载时间,并进行以下实验:
(time (require 'runtime.account :reload-all))
其中runtime.account是根模块之一。
结果,我看不到第三方库模块加载时间有差异:/。
也许您可以提供一些关于决定加载类文件还是clj文件机制的详细信息,以及一种监控该活动的方法?
谢谢!