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

欢迎!请查看关于页面以获取更多关于如何工作的信息。

0
tools.cli
重标记

tools.cli/parse-opts 接受参数、选项规格和附加选项。它调用 compile-option-specsrequired-arguments 来构建 specsreq。然后它使用这些规格和要求对提供的 args(及选项)进行验证。对于给定应用程序,前两个步骤在调用之间不会发生变化。

我提出一个新的 make-parse-opts-fn 函数,它预先执行 compile-option-specsrequired-arguments,并返回一个依赖于编译的 specsreq 的函数。它可以这样使用:(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

如果对此感兴趣,我可以提供补丁。

您能否解释在应用程序的单次运行中多次解析命令行参数的使用案例?

我毫不怀疑您的基准测试表明,预先编译然后多次解析比多次运行整个过程更快 - 但我不理解这有什么用。
阅读说明中提到的两个用途是“按顺序处理子命令”和运行测试。我最初进行这个尝试时,以为预编译可以在AOT编译时帮助单个运行,但实际上我认为这不是真的。然而,这种分割对我来说在运行我的测试套件时略微有帮助,其中我通过CLI界面多次调用代码。
在“按顺序处理子命令”的情况下,这通常在启动时只执行一次,除非你正在编写某种交互式shell(可能具有不同的语法,对cli工具的兼容性也不是那么好)。

如果您觉得有必要,我可以将私有函数暴露出来,这样您就可以为预处理/编译编写自己的包装器,但这并不感觉是一个需要直接将其嵌入到API中的编译用途案例。
这确实只执行一次,我考虑的是按顺序处理子命令并连续多次调用parse-opts。

我认为公开调用parse-opts中的私有函数会很好,但我不再确信预编译是一个好主意。可能通过执行编译并将产生的数据复制粘贴回我的代码中,然后编写一个使用手动编译的opts的parse-opts第二部分的函数,会提高速度。

是的,使编译函数公开(在文档字符串中注明预期隐私),至少可以让我更容易地尝试这项实验。
诺亚,由于你可以调用私有函数(使用 '#' 来引用它们的变量),你介意进行那些实验——如果它们显示出值得改进的地方,那么我会继续把相关部分公开。谢谢。
嗨,肖恩!在尝试了大约9个月之后,我认为应该改变的是,我希望 `cli/summarize` 是公开的。我将 `:summary-fn identity` 传递给 `cli/parse-opts` 以避免构建总结字符串,只有当用户请求帮助文档时才调用 `(#'cli/summarize summary)`。我可以在它为私有时访问它(如所演示),但这会带来重新引用的成本,我希望避免。
开玩笑的,`cli/summarize` 已经公开了。我想是文档字符串让我认为它是私有的,我从未真正检查过哦。我希望我知道如何阅读。:叹气
所以…听起来TCLI-101可以关闭了,不需要采取任何行动,对吗?
是的,谢谢你。

1 答案

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