Clojure 2024年调查问卷中分享您的想法!

欢迎!请参阅关于页面,了解更多关于本平台的信息。

0
tools.cli
重新标记

tools.cli/parse-opts 接受参数列表,选项规范和附加选项。它调用 compile-option-specsrequired-arguments 生成 specsreq。然后,它使用这些规格和要求对提供的参数进行检查(包括选项)。对于特定应用程序,前两个步骤调用之间不会变化。

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

使用criterion进行的微基准测试显示,速度提高了不止两倍(首先是 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界面多次调用代码。
关于“按顺序处理子命令”,这通常只会在启动时执行一次,除非你正在编写某种交互式外壳(其可能有不同的语法,但并不适合cli工具)。

如果那样做能帮到你,我很乐意将私有函数变为公开以便你可以编写自己的预处理/编译包装器,但这感觉并不是一个足够编译以致直接嵌入API的场景。
这是真的,它只发生一次,我之前考虑的是连续多次处理子命令并调用parse-opts。

我认为将parse-opts中调用的私有函数公开化会很好,但我不再认为预编译是一个好主意。也许通过执行编译然后将结果数据粘贴回我的代码中,并编写一个使用手动编译的opts的parse-opts第二部分的功能,可以获得速度上的提升?

是的,使编译函数公开(在文档字符串中注明隐私意图)至少会让我更容易实验。
诺亚,既然你可以调用私有函数(使用 '#' 来引用它们的变量),你能否先去做那些实验 —— 如果它们显示出有价值的改进,我就会继续将相关的部分公开。谢谢。
嗨,肖恩!经过大约9个月的尝试,我认为应该更改的部分是,我希望 `cli/summarize` 是公开的。我向 `cli/parse-opts` 传递 `:summary-fn identity` 以避免构建总结字符串,只有当用户请求帮助文档时才调用 `(#'cli/summarize summary)`。我可以访问它如果它是私有的(如所示),但这会有解引用的成本,我希望避免这个成本。
不,不是这样的,`cli/summarize` 已经是公开的。我认为文档字符串让我误以为它是私有的,我从未真正检查过。我希望我能学会阅读。:sob
那么……看起来TCLI-101可以关闭,无需采取任何行动了吗?
是的,谢谢。

1 个答案

+1
by
选定 by
 
最佳答案
...