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

欢迎!请参阅关于页面获取有关如何使用本站的信息。

0
tools.cli
重定标签

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 进行的微基准测试表明速度提高了超过两倍(先编译解析器,然后是预编译解析器)

; 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中调用的私有函数公开会很好,但我不再确信预编译是个好主意。也许通过编译然后将结果数据复制粘贴回我的代码中,写入一个use-parsed-opts结尾的函数会更快?

是的,将编译函数公开(在文档字符串中标明其隐私意图)至少会使我可以更容易地试验这一点。
诺亚,既然你能调用私有函数(使用#'来引用它们的变量),你能否先进行那些实验——如果它们显示出有价值的改进,然后我会进一步公开相关部分。谢谢。
by
嗨,肖恩!经过大约9个月的各种尝试后,我认为应该更改的是我希望`cli/summarize`成为公开。我将`:summary-fn identity`传递给`cli/parse-opts`以避免构建总结字符串,只在用户请求帮助文档时调用`(#'cli/summarize summary)`。当它是私有的(如所示)时,我可以访问它,但它有解引用Cost,我更希望避免。
by
开个玩笑,`cli/summarize`已经是公开的。我认为文档字符串让我错误地认为它是私有的,而我从未真正检查过lol。我希望我能学会如何阅读。:cry
by
所以……好像TCLI-101可以完成任务,不需要采取任何行动?
by
是的,谢谢。

1 答案

+1

已选中 توسط
 
最佳答案
...