嗨!
我阅读了关于在开发过程中减少 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 文件机制的细节,以及某些用于监控该活动的途径?
谢谢!