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

欢迎!请查阅关于页面,了解更多关于如何使用本站的信息。

+4
Clojure CLI 问:
已封闭 封闭者:

Hi Clojure 团队,

在 Liftoff,我们是 Clojure 的大用户(250 多个项目,约 40 万行代码)。我们已经构建了一些工具,可以自动根据项目代码的静态分析生成 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))))
...