Repository navigation
perf: CLI shell completion generation is slow #9686
Copy link
Copy link
Closed
Labels
bugSomething isn't workingSomething isn't workingdiscussFeature changes that require discussion primarily among the GitHub CLI teamFeature changes that require discussion primarily among the GitHub CLI teammore-info-neededMore info needed from user/contributorMore info needed from user/contributorneeds-triageneeds to be reviewedneeds to be reviewed
Description
Describe the bug
I am sensitive to my shell's startup time. I want to enable gh completions for my shell, but doing so adds 50ms to my startup time which is uncomfortable to me.
gh version 2.57.0 (2024-09-16)
https://github.com/cli/cli/releases/tag/v2.57.0
Steps to reproduce the behavior
$ hyperfine -w2 "gh completion -s bash" "bash -c 'source <(gh completion -s bash)'" "gh completion -s zsh" "zsh -c 'source <(gh completion -s zsh)'" "fzf --zsh" "zsh -c 'source <(fzf --zsh)'" "jump shell" "zsh -c 'source <(jump shell)'"
Benchmark 1: gh completion -s bash
Time (mean ± σ): 43.6 ms ± 1.0 ms [User: 42.2 ms, System: 6.6 ms]
Range (min … max): 42.4 ms … 49.1 ms 62 runs
Benchmark 2: bash -c 'source <(gh completion -s bash)'
Time (mean ± σ): 48.9 ms ± 1.0 ms [User: 44.5 ms, System: 8.9 ms]
Range (min … max): 47.2 ms … 52.1 ms 55 runs
Benchmark 3: gh completion -s zsh
Time (mean ± σ): 44.0 ms ± 3.1 ms [User: 42.6 ms, System: 6.6 ms]
Range (min … max): 41.7 ms … 66.2 ms 60 runs
Benchmark 4: zsh -c 'source <(gh completion -s zsh)'
Time (mean ± σ): 49.9 ms ± 1.2 ms [User: 43.2 ms, System: 10.4 ms]
Range (min … max): 47.6 ms … 52.9 ms 56 runs
Benchmark 5: fzf --zsh
Time (mean ± σ): 2.8 ms ± 0.6 ms [User: 1.1 ms, System: 1.1 ms]
Range (min … max): 1.5 ms … 5.8 ms 414 runs
Warning: Command took less than 5 ms to complete.
Benchmark 6: zsh -c 'source <(fzf --zsh)'
Time (mean ± σ): 8.9 ms ± 2.0 ms [User: 3.1 ms, System: 3.5 ms]
Range (min … max): 6.5 ms … 33.8 ms 235 runs
Benchmark 7: jump shell
Time (mean ± σ): 2.2 ms ± 1.2 ms [User: 0.8 ms, System: 0.9 ms]
Range (min … max): 1.4 ms … 24.5 ms 518 runs
Warning: Command took less than 5 ms to complete.
Benchmark 8: zsh -c 'source <(jump shell)'
Time (mean ± σ): 9.7 ms ± 1.2 ms [User: 4.1 ms, System: 3.2 ms]
Range (min … max): 7.7 ms … 14.3 ms 206 runs
Summary
jump shell ran
1.24 ± 0.75 times faster than fzf --zsh
3.97 ± 2.37 times faster than zsh -c 'source <(fzf --zsh)'
4.34 ± 2.47 times faster than zsh -c 'source <(jump shell)'
19.45 ± 10.80 times faster than gh completion -s bash
19.66 ± 10.99 times faster than gh completion -s zsh
21.82 ± 12.12 times faster than bash -c 'source <(gh completion -s bash)'
22.29 ± 12.38 times faster than zsh -c 'source <(gh completion -s zsh)'Expected vs actual behavior
Tools like fzf and jump incur a much lower overhead to my startup time. I expected gh to be similar.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workingdiscussFeature changes that require discussion primarily among the GitHub CLI teamFeature changes that require discussion primarily among the GitHub CLI teammore-info-neededMore info needed from user/contributorMore info needed from user/contributorneeds-triageneeds to be reviewedneeds to be reviewed
Activity
williammartin commentedon Oct 3, 2024
@vegerot thanks for opening this. What would be the maximum amount of time you'd find acceptable? There's probably some low hanging fruit we could address here but we'll probably hit diminishing returns pretty quickly since we're at the mercy of our dependencies. Finger in the air I don't think we'd get much below 15-20ms (computer dependent of course).
As a very quick win you can set
TCELL_MINIMIZE=1which is by far the biggest time sink:We had done some work previously to make this permanent but looking at it I think it's flaky. We can definitely revisit that.
If this is still too much for you, I think the only real solution is to produce the completions once each time we release a new version and put that into your shell startup scripts.
BagToad commentedon Oct 3, 2024
To add to this, cobra generally recommends executing once anyway. Though I definitely recognize that it could be less convenient than executing each time.
vegerot commentedon Oct 3, 2024
@williammartin thank you! This made a big improvement.
Why?
fzfandjumpcan quickly generate the completionswilliammartin commentedon Oct 3, 2024
The completion generation isn't the slow part, it only takes a few
ms. I think the rest of the time is spent by the runtime initialising packages. There might be a few more quick wins but as you can see it diminishes pretty quickly (and I think these are parallelised where possible, though I haven't confirmed that).fzfandjumphave significantly fewer dependencies.Still, I'll think on it!
feat(zsh): add gh completion
feat(zsh): add gh completion
vegerot commentedon Oct 4, 2024
That makes sense. Thanks! It ended up adding around 25ms to my start time.
You can see vegerot/dotfiles@87b5ba9 for more info
BagToad commentedon Oct 7, 2024
👋 @vegerot I spoke to @williammartin more on this and we opened #9724 to investigate
ghstart-up time more broadly in the future.With that, I will close this in favour of #9724