2024 Clojure状态调查!分享您的想法。

欢迎!请在关于页面获取更多关于如何使用本站的信息。

+4
Clojure CLI
已关闭

Hi Clojure团队,

在Liftoff,我们是Clojure的大使用者(250多个项目,400k行LOC)。我们为项目创建了一些自动生成deps.edn文件的工具,它基于项目代码的静态分析。

我们的一些工具和测试代码反复调用clojure.tools.deps.alpha/resolve-deps。从版本v0.14.1178开始,我们注意到以下情况

  • resolve-deps在每次调用时都会创建一个新的java.util.concurrent.ExecutorService,但在返回之前并没有关闭它(代码)。这导致我们的测试代码产生了2k以上的线程。
  • clojure.tools.deps.alpha.util.concurrent/submit-task将线程绑定推送到一个固定大小的线程池中,但不会弹出(代码)。由于线程被复用,帧堆栈持续增长。

在内部,我们现在正在使用一个修复版的工具,它在每次调用resolve-deps时无条件地关闭ExecutorService,并为每个任务弹出线程绑定。这解决了我们的问题,但我们不知道这是否是正确的解决方案。

核心Clojure团队是如何在CLI工具的背景下考虑并发性的?我们能期待未来CLI工具的发布中改进这种行为吗?

谢谢!

已关闭并附注:在Clojure CLI 1.11.1.1347中发布

2 个回答

+2
الهوية الشخصية
选中
 
最佳答案

谢谢!这些问题很重要,tools.deps肯定应该表现得更好。由于许多tools.deps的使用都是在一次性的用例中(如CLI),所以在那里它并不重要,但同意这些都是问题。

已记录在 https://clojure.atlassian.net/browse/TDEPS-227,如果您有补丁,我很乐意考虑。有关流程,请参阅 https://clojure.org/dev/dev#_becoming_a_contributor

الهوية الشخصية
嗨亚历克斯。感谢您的迅速回复。我愿意贡献补丁,但我不确定如何签署贡献协议。我的雇主对我的贡献有权利,但我没有权限将我的雇主绑定。我们该如何进行?
要么您的雇主签署,否则很遗憾我们无法接受您的贡献。
0
الهوية الشخصية

以下是一个提议的补丁

diff --git a/src/main/clojure/clojure/tools/deps/alpha.clj b/src/main/clojure/clojure/tools/deps/alpha.clj
index ec0561f1..70bef534 100644
--- a/src/main/clojure/clojure/tools/deps/alpha.clj
+++ b/src/main/clojure/clojure/tools/deps/alpha.clj
@@ -489,16 +489,20 @@
   {:arglists '([deps-map args-map])}
   ([deps-map args-map]
    (let [{:keys [extra-deps default-deps override-deps threads trace]} args-map
-         n (or threads concurrent/processors)
-         executor (concurrent/new-executor n)
          deps (merge (:deps deps-map) extra-deps)
-         version-map (-> deps
-                       (canonicalize-deps deps-map)
-                       (expand-deps default-deps override-deps deps-map executor trace)
-                       cut-orphans)
-         lib-map (lib-paths version-map)
-         lib-map' (download-libs executor lib-map deps-map)]
-     (with-meta lib-map' (meta version-map))))
+         n (or threads concurrent/processors)
+         executor (concurrent/new-executor n)]
+     (try
+       (let [version-map (-> deps
+                             (canonicalize-deps deps-map)
+                             (expand-deps default-deps override-deps deps-map executor trace)
+                             cut-orphans)
+             lib-map (lib-paths version-map)
+             lib-map' (download-libs executor lib-map deps-map)]
+         (with-meta lib-map' (meta version-map)))
+       (finally
+         ;; Shutdown executor to avoid creating too many threads.
+         (.shutdownNow executor)))))
   ;; deprecated arity, retained for backwards compatibility
   ([deps-map args-map settings]
    (resolve-deps deps-map (merge args-map settings))))
...