ericcornelissen / rust-rm

A CLI like the GNU version of rm(1) but more modern and designed for humans.
Apache License 2.0
4 stars 0 forks source link

Consider alternative argument parsing library #38

Open ericcornelissen opened 1 year ago

ericcornelissen commented 1 year ago

Technical Change

Summary

This project currently uses the clap crate for CLI argument parsing. Clap is easy to work with, concise, and provides a lot out of the box. However, it is not small (see "Size Analysis" section for more details).

As such, it might be worth investigating alternative argument parsing libraries for this project. After all, this project doesn't require anything special, just:

Requirements

Alternatives

[^1]: Based on https://github.com/rosetta-rs/argparse-rosetta-rs/tree/ec59407e70cb8993f9a81f8b2c3df1397fe84422#results derived code is less optimized for size.

Size Analysis

Using cargo-bloat we can find the functions of the executable that take up the most space. For example, of the 25 biggest functions, 15 are clap-related:

$ cargo bloat --release -n 25                    
    Finished release [optimized] target(s) in 0.09s
    Analyzing target/release/rust-rm

 File  .text     Size        Crate Name
 3.3%   4.9%  31.1KiB          std std::backtrace_rs::symbolize::gimli::resolve::{{closure}}
 2.9%   4.3%  27.5KiB clap_builder clap_builder::parser::parser::Parser::get_matches_with
 2.4%   3.5%  22.4KiB          std addr2line::ResDwarf<R>::parse
 1.8%   2.7%  17.0KiB     rust_rm? <rust_rm::cli::Args as clap_builder::derive::CommandFactory>::command
 1.7%   2.5%  16.1KiB        trash <chrono::format::DelayedFormat<I> as core::fmt::Display>::fmt
 1.5%   2.3%  14.4KiB clap_builder clap_builder::parser::validator::Validator::validate
 1.4%   2.0%  13.0KiB        trash trash::platform::<impl trash::TrashContext>::delete_all_canonicalized
 1.2%   1.7%  11.0KiB          std addr2line::ResUnit<R>::parse_lines
 1.1%   1.7%  10.6KiB      rust_rm rust_rm::main
 1.1%   1.6%  10.4KiB clap_builder clap_builder::error::Error<F>::exit
 1.0%   1.5%   9.3KiB clap_builder clap_builder::builder::command::Command::_build_self
 0.9%   1.3%   8.5KiB          std miniz_oxide::inflate::core::decompress
 0.8%   1.1%   7.2KiB clap_builder clap_builder::parser::parser::Parser::react
 0.6%   1.0%   6.1KiB clap_builder clap_builder::output::help_template::HelpTemplate::write_args
 0.6%   0.9%   6.0KiB clap_builder clap_builder::output::usage::Usage::write_args
 0.6%   0.9%   5.6KiB          std gimli::read::abbrev::Abbreviations::insert
 0.6%   0.9%   5.5KiB          std gimli::read::unit::parse_attribute
 0.6%   0.8%   5.3KiB clap_builder clap_builder::output::help_template::HelpTemplate::write_subcommands
 0.5%   0.8%   5.2KiB clap_builder <alloc::vec::Vec<T,A> as core::clone::Clone>::clone
 0.5%   0.8%   5.1KiB        trash trash::platform::<impl trash::TrashContext>::delete_all_canonicalized::{{closure}}
 0.5%   0.8%   4.9KiB clap_builder clap_builder::error::Error<F>::invalid_value
 0.5%   0.7%   4.6KiB clap_builder clap_builder::output::help_template::HelpTemplate::write_templated_help
 0.5%   0.7%   4.5KiB clap_builder clap_builder::output::help_template::HelpTemplate::spec_vals
 0.5%   0.7%   4.4KiB clap_builder <clap_builder::builder::value_parser::RangedI64ValueParser<T> as clap_builder::builder::value_parser::TypedValueParser>::parse_ref
 0.5%   0.7%   4.4KiB clap_builder clap_builder::parser::features::suggestions::did_you_mean_flag
38.7%  57.9% 367.3KiB              And 870 smaller methods. Use -n N to show more.
66.8% 100.0% 634.3KiB              .text section size, the file size is 949.7KiB
More stats ### `N=10` 4 of the 10 biggest function are related to `clap`: ```sh $ cargo bloat --release -n 10 Finished release [optimized] target(s) in 0.07s Analyzing target/release/rust-rm File .text Size Crate Name 3.3% 4.9% 31.1KiB std std::backtrace_rs::symbolize::gimli::resolve::{{closure}} 2.9% 4.3% 27.5KiB clap_builder clap_builder::parser::parser::Parser::get_matches_with 2.4% 3.5% 22.4KiB std addr2line::ResDwarf::parse 1.8% 2.7% 17.0KiB rust_rm? ::command 1.7% 2.5% 16.1KiB trash as core::fmt::Display>::fmt 1.5% 2.3% 14.4KiB clap_builder clap_builder::parser::validator::Validator::validate 1.4% 2.0% 13.0KiB trash trash::platform::::delete_all_canonicalized 1.2% 1.7% 11.0KiB std addr2line::ResUnit::parse_lines 1.1% 1.7% 10.6KiB rust_rm rust_rm::main 1.1% 1.6% 10.4KiB clap_builder clap_builder::error::Error::exit 47.8% 71.6% 454.0KiB And 885 smaller methods. Use -n N to show more. 66.8% 100.0% 634.3KiB .text section size, the file size is 949.7KiB ``` ### `N=50` 26 of the 50 biggest function are related to `clap`: ```sh $ cargo bloat --release -n 50 Finished release [optimized] target(s) in 0.07s Analyzing target/release/rust-rm File .text Size Crate Name 3.3% 4.9% 31.1KiB std std::backtrace_rs::symbolize::gimli::resolve::{{closure}} 2.9% 4.3% 27.5KiB clap_builder clap_builder::parser::parser::Parser::get_matches_with 2.4% 3.5% 22.4KiB std addr2line::ResDwarf::parse 1.8% 2.7% 17.0KiB rust_rm? ::command 1.7% 2.5% 16.1KiB trash as core::fmt::Display>::fmt 1.5% 2.3% 14.4KiB clap_builder clap_builder::parser::validator::Validator::validate 1.4% 2.0% 13.0KiB trash trash::platform::::delete_all_canonicalized 1.2% 1.7% 11.0KiB std addr2line::ResUnit::parse_lines 1.1% 1.7% 10.6KiB rust_rm rust_rm::main 1.1% 1.6% 10.4KiB clap_builder clap_builder::error::Error::exit 1.0% 1.5% 9.3KiB clap_builder clap_builder::builder::command::Command::_build_self 0.9% 1.3% 8.5KiB std miniz_oxide::inflate::core::decompress 0.8% 1.1% 7.2KiB clap_builder clap_builder::parser::parser::Parser::react 0.6% 1.0% 6.1KiB clap_builder clap_builder::output::help_template::HelpTemplate::write_args 0.6% 0.9% 6.0KiB clap_builder clap_builder::output::usage::Usage::write_args 0.6% 0.9% 5.6KiB std gimli::read::abbrev::Abbreviations::insert 0.6% 0.9% 5.5KiB std gimli::read::unit::parse_attribute 0.6% 0.8% 5.3KiB clap_builder clap_builder::output::help_template::HelpTemplate::write_subcommands 0.5% 0.8% 5.2KiB clap_builder as core::clone::Clone>::clone 0.5% 0.8% 5.1KiB trash trash::platform::::delete_all_canonicalized::{{closure}} 0.5% 0.8% 4.9KiB clap_builder clap_builder::error::Error::invalid_value 0.5% 0.7% 4.6KiB clap_builder clap_builder::output::help_template::HelpTemplate::write_templated_help 0.5% 0.7% 4.5KiB clap_builder clap_builder::output::help_template::HelpTemplate::spec_vals 0.5% 0.7% 4.4KiB clap_builder as clap_builder::builder::value_parser::TypedValueParser>::parse_ref 0.5% 0.7% 4.4KiB clap_builder clap_builder::parser::features::suggestions::did_you_mean_flag 0.5% 0.7% 4.3KiB clap_builder clap_builder::output::usage::Usage::get_required_usage_from 0.4% 0.6% 4.1KiB std addr2line::function::Function::parse_children 0.4% 0.6% 3.7KiB rust_rm rust_rm::walk::recurse_path 0.4% 0.6% 3.7KiB clap_builder clap_builder::output::help_template::HelpTemplate::write_all_args 0.4% 0.6% 3.6KiB chrono chrono::offset::local::tz_info::parser::parse 0.4% 0.6% 3.5KiB std core::slice::sort::recurse 0.4% 0.5% 3.4KiB clap_builder clap_builder::output::help_template::HelpTemplate::help 0.4% 0.5% 3.4KiB std std::backtrace_rs::symbolize::gimli::Context::new 0.4% 0.5% 3.3KiB clap_builder clap_builder::parser::features::suggestions::did_you_mean 0.3% 0.5% 3.3KiB std <&T as core::fmt::Display>::fmt 0.3% 0.5% 3.3KiB chrono chrono::offset::local::inner::current_zone 0.3% 0.5% 3.2KiB clap_lex core::num::dec2flt::dec2flt 0.3% 0.5% 3.0KiB std gimli::read::line::parse_attribute 0.3% 0.5% 3.0KiB std rustc_demangle::try_demangle 0.3% 0.5% 2.9KiB clap_builder clap_builder::builder::arg::Arg::stylize_arg_suffix 0.3% 0.5% 2.9KiB clap_builder clap_builder::error::Error::unknown_argument 0.3% 0.5% 2.9KiB std std::backtrace_rs::symbolize::gimli::elf::::new_debug 0.3% 0.4% 2.7KiB rust_rm rust_rm::transform::interactive 0.3% 0.4% 2.7KiB clap_builder clap_builder::parser::arg_matcher::ArgMatcher::fill_in_global_values 0.3% 0.4% 2.7KiB std gimli::read::rnglists::RngListIter::next 0.3% 0.4% 2.7KiB [Unknown] main 0.3% 0.4% 2.6KiB clap_builder clap_builder::output::usage::Usage::create_help_usage 0.3% 0.4% 2.5KiB clap_builder clap_builder::builder::command::Command::_build_subcommand 0.3% 0.4% 2.5KiB strsim strsim::jaro 0.3% 0.4% 2.4KiB clap_builder clap_builder::parser::matches::arg_matches::ArgMatches::remove_one 30.4% 45.6% 289.1KiB And 845 smaller methods. Use -n N to show more. 66.8% 100.0% 634.3KiB .text section size, the file size is 949.7KiB ``` ### `N=100` 37 of the 100 biggest function are related to `clap`: ```sh $ cargo bloat --release -n 100 Finished release [optimized] target(s) in 0.08s Analyzing target/release/rust-rm File .text Size Crate Name 3.3% 4.9% 31.1KiB std std::backtrace_rs::symbolize::gimli::resolve::{{closure}} 2.9% 4.3% 27.5KiB clap_builder clap_builder::parser::parser::Parser::get_matches_with 2.4% 3.5% 22.4KiB std addr2line::ResDwarf::parse 1.8% 2.7% 17.0KiB rust_rm? ::command 1.7% 2.5% 16.1KiB trash as core::fmt::Display>::fmt 1.5% 2.3% 14.4KiB clap_builder clap_builder::parser::validator::Validator::validate 1.4% 2.0% 13.0KiB trash trash::platform::::delete_all_canonicalized 1.2% 1.7% 11.0KiB std addr2line::ResUnit::parse_lines 1.1% 1.7% 10.6KiB rust_rm rust_rm::main 1.1% 1.6% 10.4KiB clap_builder clap_builder::error::Error::exit 1.0% 1.5% 9.3KiB clap_builder clap_builder::builder::command::Command::_build_self 0.9% 1.3% 8.5KiB std miniz_oxide::inflate::core::decompress 0.8% 1.1% 7.2KiB clap_builder clap_builder::parser::parser::Parser::react 0.6% 1.0% 6.1KiB clap_builder clap_builder::output::help_template::HelpTemplate::write_args 0.6% 0.9% 6.0KiB clap_builder clap_builder::output::usage::Usage::write_args 0.6% 0.9% 5.6KiB std gimli::read::abbrev::Abbreviations::insert 0.6% 0.9% 5.5KiB std gimli::read::unit::parse_attribute 0.6% 0.8% 5.3KiB clap_builder clap_builder::output::help_template::HelpTemplate::write_subcommands 0.5% 0.8% 5.2KiB clap_builder as core::clone::Clone>::clone 0.5% 0.8% 5.1KiB trash trash::platform::::delete_all_canonicalized::{{closure}} 0.5% 0.8% 4.9KiB clap_builder clap_builder::error::Error::invalid_value 0.5% 0.7% 4.6KiB clap_builder clap_builder::output::help_template::HelpTemplate::write_templated_help 0.5% 0.7% 4.5KiB clap_builder clap_builder::output::help_template::HelpTemplate::spec_vals 0.5% 0.7% 4.4KiB clap_builder as clap_builder::builder::value_parser::TypedValueParser>::parse_ref 0.5% 0.7% 4.4KiB clap_builder clap_builder::parser::features::suggestions::did_you_mean_flag 0.5% 0.7% 4.3KiB clap_builder clap_builder::output::usage::Usage::get_required_usage_from 0.4% 0.6% 4.1KiB std addr2line::function::Function::parse_children 0.4% 0.6% 3.7KiB rust_rm rust_rm::walk::recurse_path 0.4% 0.6% 3.7KiB clap_builder clap_builder::output::help_template::HelpTemplate::write_all_args 0.4% 0.6% 3.6KiB chrono chrono::offset::local::tz_info::parser::parse 0.4% 0.6% 3.5KiB std core::slice::sort::recurse 0.4% 0.5% 3.4KiB clap_builder clap_builder::output::help_template::HelpTemplate::help 0.4% 0.5% 3.4KiB std std::backtrace_rs::symbolize::gimli::Context::new 0.4% 0.5% 3.3KiB clap_builder clap_builder::parser::features::suggestions::did_you_mean 0.3% 0.5% 3.3KiB std <&T as core::fmt::Display>::fmt 0.3% 0.5% 3.3KiB chrono chrono::offset::local::inner::current_zone 0.3% 0.5% 3.2KiB clap_lex core::num::dec2flt::dec2flt 0.3% 0.5% 3.0KiB std gimli::read::line::parse_attribute 0.3% 0.5% 3.0KiB std rustc_demangle::try_demangle 0.3% 0.5% 2.9KiB clap_builder clap_builder::builder::arg::Arg::stylize_arg_suffix 0.3% 0.5% 2.9KiB clap_builder clap_builder::error::Error::unknown_argument 0.3% 0.5% 2.9KiB std std::backtrace_rs::symbolize::gimli::elf::::new_debug 0.3% 0.4% 2.7KiB rust_rm rust_rm::transform::interactive 0.3% 0.4% 2.7KiB clap_builder clap_builder::parser::arg_matcher::ArgMatcher::fill_in_global_values 0.3% 0.4% 2.7KiB std gimli::read::rnglists::RngListIter::next 0.3% 0.4% 2.7KiB [Unknown] main 0.3% 0.4% 2.6KiB clap_builder clap_builder::output::usage::Usage::create_help_usage 0.3% 0.4% 2.5KiB clap_builder clap_builder::builder::command::Command::_build_subcommand 0.3% 0.4% 2.5KiB strsim strsim::jaro 0.3% 0.4% 2.4KiB clap_builder clap_builder::parser::matches::arg_matches::ArgMatches::remove_one 0.2% 0.3% 2.2KiB std <&str as core::str::pattern::Pattern>::is_contained_in 0.2% 0.3% 2.1KiB rust_rm rust_rm::rm::dispose 0.2% 0.3% 2.1KiB clap_builder clap_builder::error::Error::invalid_subcommand 0.2% 0.3% 2.1KiB clap_builder as core::clone::Clone>::clone 0.2% 0.3% 2.1KiB clap_builder core::slice::sort::merge_sort 0.2% 0.3% 2.0KiB chrono chrono::offset::local::Local::now 0.2% 0.3% 2.0KiB rust_rm rust_rm::fs::open 0.2% 0.3% 1.9KiB std std::backtrace_rs::print::BacktraceFrameFmt::print_raw_with_column 0.2% 0.3% 1.9KiB std alloc::str::::to_lowercase 0.2% 0.3% 1.8KiB clap_builder clap_builder::builder::styled_str::StyledStr::replace_newline_var 0.2% 0.3% 1.8KiB std rustc_demangle::v0::Printer::print_const 0.2% 0.3% 1.8KiB std rustc_demangle::v0::Printer::print_path 0.2% 0.3% 1.8KiB clap_builder clap_builder::parser::matches::arg_matches::ArgMatches::remove_many 0.2% 0.3% 1.7KiB std ::fmt::fmt_decimal 0.2% 0.3% 1.7KiB std as alloc::vec::spec_from_iter::SpecFromIter>::from_iter 0.2% 0.3% 1.7KiB rust_rm? ::log 0.2% 0.3% 1.6KiB rust_rm rust_rm::walk::recurse::{{closure}} 0.2% 0.3% 1.6KiB std ::fmt 0.2% 0.3% 1.6KiB clap_builder clap_builder::parser::parser::Parser::add_defaults 0.2% 0.3% 1.6KiB chrono chrono::offset::local::tz_info::rule::RuleDay::transition_date 0.2% 0.2% 1.6KiB std core::str::count::do_count_chars 0.2% 0.2% 1.5KiB once_cell once_cell::imp::initialize_or_wait 0.2% 0.2% 1.5KiB clap_builder clap_builder::parser::parser::Parser::start_custom_arg 0.2% 0.2% 1.5KiB std core::ops::function::impls:: for &mut F>::call_mut 0.2% 0.2% 1.5KiB clap_builder clap_builder::parser::parser::Parser::possible_subcommand 0.2% 0.2% 1.5KiB std std::backtrace_rs::symbolize::gimli::elf::Object::parse 0.2% 0.2% 1.5KiB std ::next_back 0.2% 0.2% 1.4KiB std as core::iter::traits::iterator::Iterator>::next 0.2% 0.2% 1.4KiB std ::fmt 0.1% 0.2% 1.4KiB std ::fmt 0.1% 0.2% 1.4KiB chrono ::fmt 0.1% 0.2% 1.4KiB std miniz_oxide::inflate::core::init_tree 0.1% 0.2% 1.4KiB chrono chrono::offset::local::tz_info::timezone::TimeZone::from_posix_tz 0.1% 0.2% 1.3KiB std std::fs::DirBuilder::create_dir_all 0.1% 0.2% 1.3KiB std std::panicking::rust_panic_with_hook 0.1% 0.2% 1.3KiB clap_builder clap_builder::output::help_template::HelpTemplate::sc_spec_vals 0.1% 0.2% 1.3KiB std rustc_demangle::v0::Printer::print_const_str_literal 0.1% 0.2% 1.3KiB chrono chrono::offset::local::tz_info::rule::TransitionRule::from_tz_string 0.1% 0.2% 1.3KiB std rustc_demangle::v0::Printer::print_quoted_escaped_chars 0.1% 0.2% 1.3KiB std alloc::str::::replace 0.1% 0.2% 1.3KiB std rustc_demangle::v0::Printer::print_type::{{closure}} 0.1% 0.2% 1.3KiB clap_builder as core::iter::traits::iterator::Iterator>::fold 0.1% 0.2% 1.3KiB std ::fmt 0.1% 0.2% 1.3KiB clap_builder clap_builder::error::format::did_you_mean 0.1% 0.2% 1.3KiB std core::str::pattern::StrSearcher::new 0.1% 0.2% 1.3KiB std rustc_demangle::v0::Printer::print_type 0.1% 0.2% 1.2KiB std gimli::read::unit::skip_attributes 0.1% 0.2% 1.2KiB anstyle ::fmt 0.1% 0.2% 1.2KiB std ::fmt 0.1% 0.2% 1.2KiB chrono chrono::offset::local::tz_info::timezone::TimeZone::new 22.2% 33.3% 211.2KiB And 795 smaller methods. Use -n N to show more. 66.8% 100.0% 634.3KiB .text section size, the file size is 949.7KiB ```
blyxxyz commented 1 year ago

You might be interested in these benchmarks.

There are also features you don't use now but might want to have in the future:

ericcornelissen commented 1 year ago

Thanks for chiming in @blyxxyz, the benchmarks are very useful and so are the other suggestions. In fact, I created an issue to support invalid Unicode paths. I also added the considerations to the issue description as (for now) potential requirements.