2024年Clojure现状调查!中分享您的想法。

欢迎!请访问关于页面了解有关其工作方式的更多信息。

+4投票
Clojure CLI
关闭

Hi Clojure团队,

我们公司在Liftoff项目中广泛使用Clojure(超过400k LOC,涉及250多个项目)。我们已经开发了一些工具,这些工具根据项目的静态代码分析自动生成deps.edn文件。

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

  • resolve-deps在每次调用中都会创建一个新的java.util.concurrent.ExecutorService,但在返回之前没有关闭它(代码)。这导致我们的测试代码产生了20k+线程。
  • 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

嗨 Alex。感谢您的迅速回复。我会很高兴地贡献补丁,但我不确定如何签署贡献者协议。我的雇主对我的贡献有权利,但我没有绑定雇主的签字权。我们该如何进行?
要么您的雇主签字,要么遗憾的是我们无法接受您的贡献。
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))))
...