# Why is ArgParse slow?

**URL:** <https://discourse.julialang.org/t/why-is-argparse-slow/34741>\
**Category:** General Usage\
**Tags:** question, package, optimization\
**Created:** [February 17, 2020, 1:25am UTC](https://discourse.julialang.org/t/why-is-argparse-slow/34741 "2020-02-17T01:25:37Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![kevbonham](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kevbonham/32/216165_2.png) [@kevbonham](https://discourse.julialang.org/u/kevbonham)\
**Post date:** [February 17, 2020, 1:25am UTC](https://discourse.julialang.org/t/why-is-argparse-slow/34741/1 "2020-02-17T01:25:38Z")

</div>

I really love [ArgParse.jl](https://github.com/carlobaldassi/ArgParse.jl) - it has a ton of features, the documentation is great, and it works exactly as advertised. But it’s **slow**. Adding even a couple of arguments adds several seconds to start up time. It’s really amazing that running simple scripts in `julia` (so long as you’re not using crazy numbers of dependencies) is under a second, but adding ArgParse to this is rough.

I wanted to do a bit of testing, so I made [a tiny package](https://github.com/kescobo/ArgParseLite.jl)  
In the `bin/` folder you’ll find a couple of test scripts that do the same thing:

```julia
$ time julia --project=bin bin/lite.jl foo --opt1 bar -o baz --flag1
Parsed args:
  flag1 => true
  arg1 => foo
  opt1 => bar
  opt2 => baz
julia --project=bin bin/lite.jl foo --opt1 bar -o baz --flag1 0.87s user 0.15s system 198% cpu 0.512 total
$ time julia --project=bin bin/argparse.jl foo --opt1 bar -o baz --flag1
Parsed args:
  flag1 => true
  arg1 => foo
  opt1 => bar
  opt2 => baz
julia --project=bin bin/argparse.jl foo --opt1 bar -o baz --flag1 3.55s user 0.17s system 115% cpu 3.217 total

```

It’s not code-loading time, because adding `using ArgParse` to the `lite.jl` script doesn’t affect timing much. Could it be something about the use of macros? I tried wading through the code from `ArgParse.jl` and got bogged down in the macro stuff.

ArgParse has _a lot_ more features, but it seems unlikely that providing the ability to check types, print useful help messages and have default values could account for the difference in this simple script. That said, I’m wary of putting much more effort in before understanding what’s causing the slow down.

Note: just before posting this, I noticed @kevin.squire made [ArgParse2](https://github.com/kmsquire/ArgParse2.jl) for largely the same reasons. I haven’t tested it out, but based on the README it looks like load time was part of the motivation.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [February 17, 2020, 2:56am UTC](https://discourse.julialang.org/t/why-is-argparse-slow/34741/2 "2020-02-17T02:56:59Z")

</div>

> [@kevbonham](#):
>
> Adding even a couple of arguments adds several seconds to start up time.

Sounds like you’re just looking at compilation time?

> [@kevbonham](#):
>
> ArgParse has _a lot_ more features

Hence, more to compile.

The compilation start-up time is why Julia isn’t currently too useful for little scripts that launch Julia, do some tiny calculation, and then exit. You either want to keep Julia running (e.g. in a long interactive session where you do lots of little calculations), or use Julia for big calculations where startup compilation time doesn’t matter.

In the future, as Julia gains the ability to cache more compiled code (or compile less code — i.e. run in an interpreter mode for short calculations), this issue will go away, similar to the “time to first plot” issue.

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [February 17, 2020, 4:00am UTC](https://discourse.julialang.org/t/why-is-argparse-slow/34741/3 "2020-02-17T04:00:06Z")

</div>

FYI, I created a command line interface framework for Julia: [GitHub - tkf/JuliaCLI.jl](https://github.com/tkf/JuliaCLI.jl) I haven’t registered it yet but it already works well for me.

The idea is to have a backend server with bunch of Julia worker processes. The CLI frontend simply connects to one of the backend and run some code. The first invocation is slow as usual but from the second time it’s very fast.

Here is an example of using [JuliaFormatter.jl](https://github.com/domluna/JuliaFormatter.jl) and ArgParse.jl: [jlfmt/jlfmt.jl at master · tkf/jlfmt · GitHub](https://github.com/tkf/jlfmt/blob/master/src/jlfmt.jl). You can also have an [instantaneous REPL startup](https://github.com/tkf/JuliaCLI.jl#example-instantaneous-repl).

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [February 17, 2020, 6:39am UTC](https://discourse.julialang.org/t/why-is-argparse-slow/34741/4 "2020-02-17T06:39:20Z")

</div>

I looked into this (a tiny bit) a while ago: [use @nospecialize to help with compile time by KristofferC · Pull Request #76 · carlobaldassi/ArgParse.jl · GitHub](https://github.com/carlobaldassi/ArgParse.jl/pull/76).

I think that the code handed to LLVM just takes a long time for LLVM to optimize.

---

<div class="post-metadata">

**Author:** ![kevbonham](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kevbonham/32/216165_2.png) [@kevbonham](https://discourse.julialang.org/u/kevbonham)\
**Post date:** [February 17, 2020, 1:30pm UTC](https://discourse.julialang.org/t/why-is-argparse-slow/34741/5 "2020-02-17T13:30:32Z")

</div>

> [@stevengj](#):
>
> Hence, more to compile.

But even when many of those features aren’t used, there’s a huge slow-down. It seems to happen regardless of what goes into the `@add_arg_table` macro.

> [@stevengj](#):
>
> The compilation start-up time is why Julia isn’t currently too useful for little scripts that launch Julia, do some tiny calculation, and then exit. You either want to keep Julia running (e.g. in a long interactive session where you do lots of little calculations), or use Julia for big calculations where startup compilation time doesn’t matter.

Yeah, I know all of this - the use-case is ultimately for longer running scripts, but especially when developing and running test inputs (or just trying to check that the argument parsing is working) or if a user just runs `julia my_script.jl --help`, taking 3-5 sec for each invocation is a real pain.

> [@tkf](#):
>
> FYI, I created a command line interface framework for Julia: [https://github.com/tkf/JuliaCLI.jl](https://github.com/tkf/JuliaCLI.jl) I haven’t registered it yet but it already works well for me.

This is a super interesting idea, thanks! I’ll take a look.

> [@kristoffer.carlsson](#):
>
> I think that the code handed to LLVM just takes a long time for LLVM to optimize.

Awesome, thanks for chiming in! Does this seem to you like something that will be intrinsic to any full-featured argument parsing library, or do you think there’s something about the design of that package in particular? I see your PR got merged a while ago, but it’s still pretty slow. I’m wondering if it’s worth continuing to add features to `ArgParseLite.jl` (or more likely, contribute to `ArgParse2.jl`), or if getting to feature parity is likely to lead to the same slow-down.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [February 17, 2020, 1:45pm UTC](https://discourse.julialang.org/t/why-is-argparse-slow/34741/6 "2020-02-17T13:45:28Z")

</div>

> [@kevbonham](#):
>
> Does this seem to you like something that will be intrinsic to any full-featured argument parsing library, or do you think there’s something about the design of that package in particular?

I think it is just design choices of the package in particular. It uses a lot of Metaprogramming and the traces in the profile pointed towards NamedTuples so it might create many specializations based on values of the arguments? Tightening up some types like `String` instead of `AbstractString` everywhere might help as well.

---

<div class="post-metadata">

**Author:** ![kevbonham](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kevbonham/32/216165_2.png) [@kevbonham](https://discourse.julialang.org/u/kevbonham)\
**Post date:** [February 17, 2020, 1:56pm UTC](https://discourse.julialang.org/t/why-is-argparse-slow/34741/7 "2020-02-17T13:56:55Z")

</div>

> [@kristoffer.carlsson](#):
>
> I think it is just design choices of the package in particular.

Good to know. I guess I’ll keep going then 🙂

I just added an example using `ArgParse2.jl`:

```julia
$ time julia --project=bin bin/argparse2.jl foo --opt1 bar -o baz --flag1
Parsed args:
  arg1 => foo
  opt1 => bar
  opt2 => baz
  flag1 => true
julia --project=bin bin/argparse2.jl foo --opt1 bar -o baz --flag1 2.39s user 0.19s system 124% cpu 2.065 total

```

---

<div class="post-metadata">

**Author:** ![kevin.squire](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kevin.squire/32/62_2.png) [@kevin.squire](https://discourse.julialang.org/u/kevin.squire)\
**Post date:** [February 20, 2020, 10:28am UTC](https://discourse.julialang.org/t/why-is-argparse-slow/34741/8 "2020-02-20T10:28:51Z")

</div>

> [@kevbonham](#):
>
> Note: just before posting this, I noticed @kevin.squire made [ArgParse2](https://github.com/kmsquire/ArgParse2.jl) for largely the same reasons. I haven’t tested it out, but based on the README it looks like load time was part of the motivation

Yep, that was part of the motivation. As you can see from your example, it is a little faster, but it was also unclear to me whether any advantage would remain after adding features.

That said, I just did a little bit of timing optimization, which cut timing on your example above by ~25-30%. I’d still like it to be faster, but it seems promising, so I’m going to continue working on it, and I’ll probably register it soon. Contributions are very welcome.

Cheers,  
Kevin

---

<div class="post-metadata">

**Author:** ![dmolina](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmolina/32/5246_2.png) [@dmolina](https://discourse.julialang.org/u/dmolina)\
**Post date:** [February 20, 2020, 12:16pm UTC](https://discourse.julialang.org/t/why-is-argparse-slow/34741/9 "2020-02-20T12:16:00Z")

</div>

In this type of programs, sometimes it is useful to run julia with parameter “-O0” to reduce the initial wait (mainly in simple scripts programs, because the program could be slower in more complex programs).
