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

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

您能解释一下为什么在应用程序的单次运行中多次解析命令行参数的用例吗?

我不怀疑您提出的基准测试表明,先预编译然后再多次解析要快于多次运行整个过程——但我不明白为什么这会有用。
两个用例是“按顺序处理子命令”,如readme中所述,以及运行测试。我最初深入研究这个问题的想法是在AOT编译时预编译有助于提高单次运行的效率,但我认为这实际上并不是真的。然而,当运行我的测试套件时,我通过CLI界面调用代码很多次,这种拆分在某种程度上有所帮助。
在“按顺序处理子命令”的情况下,这通常只在启动时执行一次,除非你在编写某种交互式shell(可能具有不同的语法,对工具.cli来说可能没有这么方便)。

如果那样做可以将私有函数公开,以便您可以编写自己的预处理/编译封装,我将很高兴这样做,但这感觉并不像是一个值得直接将编译 bake 到API 中的用例。
当然,它只会发生一次,我是在想连续多次处理子命令并调用parse-opts。

我认为在parse-opts中调用的私有函数公开是好事,但我不再确信预编译是一个好主意。也许通过执行编译并将结果数据复制粘贴回我的代码中,可以写一个使用手动编译的opts的第二部分的函数。

是的,将编译函数公开(在文档字符串中注明故意性),至少使我更容易实验。
诺亚,因为你可以调用私有函数(使用 '#' 来引用它们的变量),你能否先进行那些实验——如果它们显示出值得改进的地方,那么我会将它相关的部分公开。谢谢。
嗨,肖恩!经过大约9个月的尝试和测试,我认为唯一需要改变的是我想将 `cli/summarize` 公开。我将 `:summary-fn identity` 传递给 `cli/parse-opts` 来避免构建摘要字符串,只有当用户请求帮助文档时才会调用 `(#'cli/summarize summary)`。如果它是私有的,我可以访问它(如所演示),但是这会有解引用的成本,我不想避免。
开玩笑的,`cli/summarize` 已经是公开的。我认为文档字符串让我以为它是私有的,我从未真正检查过。我希望我会看书。:泣
所以...看起来 TCLI-101 可以关闭,不需要采取任何行动了?
是的,谢谢。

1 个答案

+1

已选择
 
最佳答案
...