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

欢迎!请参阅 关于 页面,了解有关此如何运作的一些更多信息。

0
tools.cli
重新标记

工具对话框的 parse-opts 函数接受参数、选项规范和附加选项。它调用 compile-option-specsrequired-arguments 来构建 规范req。然后,它使用这些规范和 req 在提供的 args(以及选项)上执行验证。对于给定的应用程序,前两个步骤在调用之间不会改变。

我提出一个新的 make-parse-opts-fn 函数,该函数预先执行 compile-option-specsrequired-arguments,并返回一个依赖于编译的 规格req 的函数。它可以这样使用:(def compiled-parser (make-parse-opts-fn cli-options))

使用 criterium 进行的微型基准测试显示,速度增加了倍以上(tools.cli/parse-opts 第一次,预编译解析器第二次)

; user=> (def cli-options
  [["-h" "--help" "This message"]
   [nil "--extra" "Output in extra format"
    :default false]
   ["-q" "--quiet" "Print no suggestions, only return exit code"
    :default false]])
#'user/cli-options

; user=> (bench (cli/parse-opts ["--quiet" "src"] cli-options :in-order true))
Evaluation count : 10962 in 6 samples of 1827 calls.
             Execution time mean : 65.021329 µs
    Execution time std-deviation : 5.276033 µs
   Execution time lower quantile : 58.658638 µs ( 2.5%)
   Execution time upper quantile : 69.724228 µs (97.5%)
                   Overhead used : 9.607933 ns
nil

; user=> (bench (compiled-parser ["--quiet" "src"] :in-order true))
Evaluation count : 24660 in 6 samples of 4110 calls.
             Execution time mean : 25.090846 µs
    Execution time std-deviation : 253.361821 ns
   Execution time lower quantile : 24.769079 µs ( 2.5%)
   Execution time upper quantile : 25.413286 µs (97.5%)
                   Overhead used : 9.607933 ns
nil

如果将附加选项也提升到 make-parse-opts-fn 中(以速度换取灵活性),则差异更为显著,相对于现有的 tools.cli/parse-opts 函数,提供了大约 10 倍的速度提高

; user=> (bench (compiled-parser-2 ["--quiet" "src"]))
Evaluation count : 73116 in 6 samples of 12186 calls.
             Execution time mean : 8.349923 µs
    Execution time std-deviation : 51.419864 ns
   Execution time lower quantile : 8.282266 µs ( 2.5%)
   Execution time upper quantile : 8.407998 µs (97.5%)
                   Overhead used : 9.607933 ns

Found 2 outliers in 6 samples (33.3333 %)
	low-severe	 1 (16.6667 %)
	low-mild	 1 (16.6667 %)
 Variance from outliers : 13.8889 % Variance is moderately inflated by outliers
nil

如果有兴趣,我可以提供补丁。

您能解释在一个应用程序的单次运行中多次解析命令行参数的使用场景吗?

我不怀疑您的基准测试显示,首先预编译然后再多次解析比多次运行整个过程要快 —— 但我不明白这会有什么用。
以下两个用例,如README中所述,是“子命令按顺序处理”和运行测试。我最初是因为认为预编译有助于AOT编译时的单次运行才深入研究这个问题,但我不认为这实际上是有帮助的。然而,这种分割在运行我的测试套件时略微有帮助,在此过程中我多次通过CLI界面调用代码。
在“子命令按顺序处理”的情况下,这通常只是在启动时一次性执行的事情,除非你正在编写某种交互式shell(可能有不同的语法,工具的CLI接口可能不太容易适应)。

如果那对你有帮助,我很乐意将私有函数设置为公共的,这样你就可以为你自己的预处理/编译编写包装器。但这并不像将直接将它们嵌入API的用例那样充分编译。
这确实只发生一次,我在想连续多次处理子命令和调用parse-opts。

我认为将parse-opts中调用的私有函数公开会是件好事,但我不太确信预编译是一个好主意。也许可以将编译和将结果数据复制粘贴回我的代码中,然后编写一个使用手动编译的opts的第二部分parse-opts函数来获得速度上的提升?

是的,使编译函数公开(并注意在文档字符串中的隐私意图)将至少使我更容易尝试这个想法。
Noah,既然您可以调用私有函数(使用 '#' 来引用它们的变量),您能否先进行这些实验——如果发现值得改进的地方,那么我会 κάνωη τις σχετικές ενέργειες σε κοινόχρηστο. Ευχαριστώ。
嗨Sean!经过大约9个月的试验,我认为唯一需要改变的是,我希望 `cli/summarize` 是公开的。我传递 `:summary-fn identity` 给 `cli/parse-opts` 来避免构建汇总字符串,只有在用户请求帮助文档时才调用 `(#'cli/summarize summary)`。我可以在它为私有(如所展示)时访问它,但这会有解引用成本,我希望避免。
开个玩笑,`cli/summarize` 已经是公开的。我想文档字符串让我误以为是私有的,我从未真正检查过呵呵。我希望自己能读书。 :少吃
那么... 看来 TCLI-101 可以完成了,不需要采取任何行动?
是的,谢谢。

1 个回答

+1

选择了
 
最佳答案
...