zdharma-continuum / zinit

🌻 Flexible and fast ZSH plugin manager
MIT License
3.15k stars 129 forks source link

[question]: Slow performance #337

Closed avently closed 2 years ago

avently commented 2 years ago

Describe the bug

I'm not sure I'm doing everything correctly but based on my tests zinit is 4-7 times slower than antigen. Which is kind of strange because here and there I see about fast nature of zinit. So it's more a question than a bug report. What do I do wrong?

Test results of zsh start up:

# ZInit
for i in {0..10}; do time zsh -i -c exit; done
zsh -i -c exit  0,69s user 0,31s system 103% cpu 0,965 total
zsh -i -c exit  0,82s user 0,38s system 102% cpu 1,160 total
zsh -i -c exit  0,91s user 0,38s system 102% cpu 1,246 total
zsh -i -c exit  1,06s user 0,37s system 101% cpu 1,406 total
zsh -i -c exit  0,76s user 0,33s system 102% cpu 1,059 total
zsh -i -c exit  0,98s user 0,43s system 102% cpu 1,373 total
zsh -i -c exit  1,05s user 0,38s system 101% cpu 1,407 total
zsh -i -c exit  0,85s user 0,36s system 103% cpu 1,170 total
zsh -i -c exit  0,61s user 0,31s system 103% cpu 0,888 total
zsh -i -c exit  0,75s user 0,38s system 101% cpu 1,112 total
zsh -i -c exit  0,72s user 0,35s system 103% cpu 1,031 total
# Antigen
zsh -i -c exit  0,10s user 0,08s system 99% cpu 0,180 total
zsh -i -c exit  0,27s user 0,10s system 99% cpu 0,376 total
zsh -i -c exit  0,11s user 0,07s system 99% cpu 0,177 total
zsh -i -c exit  0,10s user 0,09s system 99% cpu 0,192 total
zsh -i -c exit  0,14s user 0,09s system 99% cpu 0,231 total
zsh -i -c exit  0,25s user 0,13s system 99% cpu 0,379 total
zsh -i -c exit  0,21s user 0,10s system 99% cpu 0,305 total
zsh -i -c exit  0,17s user 0,09s system 98% cpu 0,266 total
zsh -i -c exit  0,17s user 0,11s system 99% cpu 0,280 total
zsh -i -c exit  0,23s user 0,12s system 99% cpu 0,353 total
zsh -i -c exit  0,11s user 0,09s system 98% cpu 0,196 total
# Without any plugin manager (only my configs)
zsh -i -c exit  0,05s user 0,04s system 98% cpu 0,091 total
zsh -i -c exit  0,04s user 0,04s system 99% cpu 0,079 total
zsh -i -c exit  0,11s user 0,07s system 99% cpu 0,182 total
zsh -i -c exit  0,05s user 0,05s system 99% cpu 0,094 total
zsh -i -c exit  0,11s user 0,07s system 99% cpu 0,176 total
zsh -i -c exit  0,11s user 0,07s system 99% cpu 0,182 total
zsh -i -c exit  0,13s user 0,05s system 99% cpu 0,180 total
zsh -i -c exit  0,09s user 0,05s system 99% cpu 0,137 total
zsh -i -c exit  0,07s user 0,05s system 99% cpu 0,115 total
zsh -i -c exit  0,10s user 0,08s system 99% cpu 0,180 total
zsh -i -c exit  0,12s user 0,06s system 99% cpu 0,176 total

Steps to reproduce

Add it to your test .zshrc:

zsh_manager="zinit"
packages=(
"ohmyzsh/ohmyzsh"
"zdharma-continuum/fast-syntax-highlighting"
"zsh-users/zsh-autosuggestions"
"zsh-users/zsh-completions"
"zsh-users/zsh-history-substring-search"
"mfaerevaag/wd"
"b4b4r07/enhancd"
"zdharma-continuum/history-search-multi-word"
"jirutka/zsh-shift-select"
)

if [[ "$zsh_manager" == "antigen" ]]; then
    if [[ -f ~/.antigen/antigen.zsh ]]; then
    else
        mkdir ~/.antigen 2> /dev/null
        curl --silent -L git.io/antigen-nightly > ~/.antigen/antigen.zsh
    fi
   source ~/.antigen/antigen.zsh

    # When it's added via 'use' it's two times faster than with bundle
    antigen use oh-my-zsh
    for package in "${packages[@]}"; do
        [ "$package" = "zdharma-continuum/history-search-multi-word" ] && package="zdharma-continuum/history-search-multi-word@main"
        [ "$package" = "ohmyzsh/ohmyzsh" ] && continue
        antigen bundle "$package"
    done

    antigen apply
elif [[ "$zsh_manager" == "zinit" ]]; then
    ZINIT_HOME="${XDG_DATA_HOME:-${HOME}/.local/share}/zinit/zinit.git"
    if [[ ! -d "$ZINIT_HOME" ]]; then
        mkdir -p "$(dirname $ZINIT_HOME)"
        git clone https://github.com/zdharma-continuum/zinit.git "$ZINIT_HOME"
        source "${ZINIT_HOME}/zinit.zsh"
        zinit self-update
    fi
    source "${ZINIT_HOME}/zinit.zsh"

    for package in "${packages[@]}"; do
        zinit light "$package"
    done
fi

Then run:

# To prepare for the first time
zsh -i -c exit
# Test
for i in {0..10}; do time zsh -i -c exit; done

Then change zsh_manager to "antigen" Run:

# To prepare for the first time
zsh -i -c exit
# Test
for i in {0..10}; do time zsh -i -c exit; done

Compare the timings.

Expected behavior

I expect it to be the fastest plugin manager because what purpose of having so much functionality but without performance? I expect it to add 50-100 ms to startup time maximum. If this will be possible it could be a good candidate to use it for many other tasks like preparing servers in scripts with autodownloading dependencies from github releases and so on,

Screenshots and recordings

No response

Operating System & Version

linux-gnu | pc | x86_64 | x86_64 | x86_64 unknown

Zsh version

zsh 5.9 (x86_64-pc-linux-gnu)

Terminal emulator

kitty

If using WSL on Windows, which version of WSL

No response

Additional context

I use HDD in tests

vladdoster commented 2 years ago

I'd strongly suggest reading the README.md + wiki. You're not leveraging Zinit features.

The configuration here times:

Screenshot 2022-07-09 at 12 17 05
avently commented 2 years ago

@vladdoster almost every config for zinit has hundreds of lines while in other plugin managers the number of lines is number of plugins + ~5 lines. Also zinit gives the whole new language for setuping the plugins which is way harder to use than all build systems I used in my life (npm, cargo, gradle, cmake, nimble, etc). So, probably, the performance gain (if it is exists, because i'm sure that your test results were gotten from machine which is more powerful than ten year old Intel i3 like in my tests).

So, yes, looks like i'm not leveraging zinit futures.

Nevertheless, I'll try to setup it with my plugin set to compare performance.

vladdoster commented 2 years ago

Addressing points you brought up:

almost every config for zinit has hundreds of lines while in other plugin managers the number of lines is number of plugins + ~5 lines

Configurations are long for a few reasons:

  1. Zinit defaults to using the .zshrc startup file, thus which will also have Zsh specific configuration that is not pertinent to Zinit.

  2. Readability - it is very common for users to have longer configs in favor of readability. There are mechanisms that allow for reducing config length, such as:

zi for is-snippet \
  OMZL::{'clipboard','compfix','completion','git','grep','key-bindings'}.zsh \
  OMZP::brew \
  PZT::modules/{'history','rsync'}
zi as'completion' for OMZP::{'golang/_golang','pip/_pip','terraform/_terraform'}

and


zi light-mode for "$ZI_REPO"/zinit-annex-{'bin-gem-node','binary-symlink','patch-dl','submods'}

zinit gives the whole new language for setuping the plugins which is way harder to use than all build systems I used in my life (npm, cargo, gradle, cmake, nimble, etc)

It is called syntax and is no different from any of the programs you mentioned.

Additionally, you are kidding yourself if you think zinit is harder to use than cmake.

This is the index of CMake -> https://cmake.org/cmake/help/latest/genindex.html

probably, the performance gain (if it is exists, because i'm sure that your test results were gotten from machine which is more powerful than ten year old Intel i3 like in my tests).

I spun up the lowest tier VM on AWS and tested the same configuration as before:

1 GiB RAM & 1 CPU core

Screenshot 2022-07-09 at 20 09 30
avently commented 2 years ago

Actually looks like I do everything correctly. You're saying that i'm not leveraging zinit features. But "light" loading is used like it's used in perf test https://github.com/zdharma-continuum/pm-perf-test/blob/main/zinit-light/.zshrc

The only thing I can do for performance gain is to use turbo, right? https://github.com/zdharma-continuum/pm-perf-test/blob/main/zinit-turbo/.zshrc

Or is there are other optimization I can do for the provided set of plugins?

avently commented 2 years ago

Changed my config to this:

    for snipet in completion clipboard directories spectrum; do
        zinit ice wait lucid
        zinit snippet OMZ::lib/$snipet.zsh
    done
    zinit snippet OMZ::lib/key-bindings.zsh

    zinit ice wait lucid atload"_zsh_autosuggest_start"
    zinit load zsh-users/zsh-autosuggestions

    zinit ice wait lucid
    zinit light zsh-users/zsh-completions

    # No lucid load here
    zinit load zsh-users/zsh-history-substring-search

    zinit ice wait lucid
    zinit load mfaerevaag/wd

    zinit ice wait lucid
    zinit load b4b4r07/enhancd

    zinit ice wait lucid
    zinit load zdharma-continuum/history-search-multi-word

    zinit ice wait lucid
    zinit load jirutka/zsh-shift-select

    zinit ice wait lucid
    zinit load zdharma-continuum/fast-syntax-highlighting
zsh -i -c exit  0,15s user 0,07s system 98% cpu 0,227 total
zsh -i -c exit  0,16s user 0,07s system 98% cpu 0,224 total
zsh -i -c exit  0,18s user 0,06s system 97% cpu 0,251 total
zsh -i -c exit  0,14s user 0,06s system 99% cpu 0,204 total
zsh -i -c exit  0,28s user 0,10s system 99% cpu 0,390 total
zsh -i -c exit  0,17s user 0,06s system 98% cpu 0,230 total
zsh -i -c exit  0,14s user 0,08s system 99% cpu 0,223 total
zsh -i -c exit  0,29s user 0,12s system 99% cpu 0,413 total
zsh -i -c exit  0,30s user 0,10s system 99% cpu 0,405 total
zsh -i -c exit  0,16s user 0,07s system 98% cpu 0,230 total
zsh -i -c exit  0,23s user 0,09s system 99% cpu 0,316 total

Now it's comparable to antigen with an exception that antigen loads everything up and ready instead of partially.

Is there something I can do to improve load time futher?

Additionally, you are kidding yourself if you think zinit is harder to use than cmake.

It was just to make us laugh:) Note gradle in the list.

P.S. thank you for your answers. I know how hard to tell someone that he is wrong.

avently commented 2 years ago

Nevermind. Nothing can be faster than Antigen currently. It's just a magic piece of code.

Zinit on the other hand is cool as package manager. For example, I have tons of different servers which has different OSes: Arch, Ubuntu with different architecture: x86_64, arm64. Ubuntu has old versions sometimes and it's hard to manage that infrastructure without something like zinit or ansible.

vladdoster commented 2 years ago

Nevermind. Nothing can be faster than Antigen currently. It's just a magic piece of code.

This assertion would be incorrect.

Using the antigen performance test

https://github.com/zsh-users/antigen/wiki/Stats-comparative

Antigen v2.0.0 loads in .0512 seconds

The same test using Zinit on the AWS VM as before

Plugin loading times: 12 ms - zsh-users/zsh-history-substring-search 1 ms - zsh-users/zsh-completions 25 ms - zsh-users/zsh-syntax-highlighting Total: 0.038 sec [null@redacted-hostname]~%

Additionally, Antigen has not been updated in ~5+ years while Zinit is actively maintained.

vladdoster commented 2 years ago

and you can get a prompt, 2 annexes, and hyperfine binary and still load as fast as antigen

Plugin loading times:
   12 ms - sindresorhus/pure
    3 ms - zdharma-continuum/zinit-annex-binary-symlink
    5 ms - zdharma-continuum/zinit-annex-bin-gem-node
    4 ms - sharkdp/hyperfine
    8 ms - zsh-users/zsh-history-substring-search
    1 ms - zsh-users/zsh-completions
   18 ms - zsh-users/zsh-syntax-highlighting
Total: 0.051 sec
vladdoster commented 2 years ago

This was also documented here

https://raw.githubusercontent.com/zdharma-continuum/pm-perf-test/master/plots/startup-times.png

.030s

https://github.com/zdharma-continuum/pm-perf-test#results

avently commented 2 years ago

Made a test file for both plugin managers with a set of plugins that I use. Zinit loads only a subset of ohmyzsh plugins lib files while antigen loads every lib file. Zinit has an issue with autosuggestion plugin I couldn't solve so probably another one script should be preloaded without lucid mode (which will affect performance of couse). But let's say the both identical in this test (however they are not because zinit load much less files from ohmyzsh).

If you still think you're right, tell me why my code is wrong or could be better. Otherwise your still load as fast as antigen is not true in my case.

P.S.

Additionally, Antigen has not been updated in ~5+ years while Zinit is actively maintained

Zinit has a lot of features and I really like how it's doing what is it doing but I ALWAYS choose the solution that do it's job faster when we talk about everyday tasks like opening another tab in terminal. I don't want to wait forever just because the tool is so capable but slow.

To run the test:

zsh test.txt

(Github doesn't allow to upload file file with .sh extension, so use txt) test.txt

My results: Slow notebook with HDD

Hello from zinit
HOME=$PWD/zinit zsh -i -c exit  0,17s user 0,09s system 94% cpu 0,271 total
HOME=$PWD/zinit zsh -i -c exit  0,29s user 0,09s system 93% cpu 0,403 total
HOME=$PWD/zinit zsh -i -c exit  0,30s user 0,11s system 87% cpu 0,475 total
HOME=$PWD/zinit zsh -i -c exit  0,23s user 0,13s system 88% cpu 0,407 total
HOME=$PWD/zinit zsh -i -c exit  0,23s user 0,10s system 97% cpu 0,342 total
HOME=$PWD/zinit zsh -i -c exit  0,21s user 0,08s system 98% cpu 0,292 total
HOME=$PWD/zinit zsh -i -c exit  0,29s user 0,11s system 93% cpu 0,432 total
HOME=$PWD/zinit zsh -i -c exit  0,32s user 0,11s system 91% cpu 0,462 total
HOME=$PWD/zinit zsh -i -c exit  0,26s user 0,10s system 96% cpu 0,367 total
HOME=$PWD/zinit zsh -i -c exit  0,22s user 0,08s system 99% cpu 0,305 total
HOME=$PWD/zinit zsh -i -c exit  0,15s user 0,06s system 98% cpu 0,223 total
Hello from antigen
HOME=$PWD/antigen zsh -i -c exit  0,10s user 0,08s system 97% cpu 0,188 total
HOME=$PWD/antigen zsh -i -c exit  0,14s user 0,06s system 94% cpu 0,217 total
HOME=$PWD/antigen zsh -i -c exit  0,17s user 0,13s system 78% cpu 0,377 total
HOME=$PWD/antigen zsh -i -c exit  0,17s user 0,15s system 78% cpu 0,411 total
HOME=$PWD/antigen zsh -i -c exit  0,17s user 0,11s system 87% cpu 0,325 total
HOME=$PWD/antigen zsh -i -c exit  0,20s user 0,08s system 85% cpu 0,328 total
HOME=$PWD/antigen zsh -i -c exit  0,16s user 0,10s system 92% cpu 0,278 total
HOME=$PWD/antigen zsh -i -c exit  0,15s user 0,06s system 95% cpu 0,223 total
HOME=$PWD/antigen zsh -i -c exit  0,16s user 0,07s system 98% cpu 0,228 total
HOME=$PWD/antigen zsh -i -c exit  0,11s user 0,06s system 97% cpu 0,173 total
HOME=$PWD/antigen zsh -i -c exit  0,14s user 0,06s system 98% cpu 0,207 total

Cloud server with SSD

Hello from zinit
HOME=$PWD/zinit zsh -i -c exit  0,04s user 0,02s system 88% cpu 0,069 total
HOME=$PWD/zinit zsh -i -c exit  0,06s user 0,02s system 92% cpu 0,084 total
HOME=$PWD/zinit zsh -i -c exit  0,05s user 0,02s system 88% cpu 0,078 total
HOME=$PWD/zinit zsh -i -c exit  0,05s user 0,01s system 98% cpu 0,065 total
HOME=$PWD/zinit zsh -i -c exit  0,04s user 0,02s system 97% cpu 0,062 total
HOME=$PWD/zinit zsh -i -c exit  0,04s user 0,02s system 99% cpu 0,058 total
HOME=$PWD/zinit zsh -i -c exit  0,05s user 0,01s system 99% cpu 0,061 total
HOME=$PWD/zinit zsh -i -c exit  0,04s user 0,01s system 99% cpu 0,059 total
HOME=$PWD/zinit zsh -i -c exit  0,04s user 0,02s system 98% cpu 0,066 total
HOME=$PWD/zinit zsh -i -c exit  0,05s user 0,01s system 98% cpu 0,061 total
HOME=$PWD/zinit zsh -i -c exit  0,05s user 0,01s system 98% cpu 0,059 total
Hello from antigen
HOME=$PWD/antigen zsh -i -c exit  0,04s user 0,01s system 98% cpu 0,046 total
HOME=$PWD/antigen zsh -i -c exit  0,02s user 0,02s system 99% cpu 0,043 total
HOME=$PWD/antigen zsh -i -c exit  0,03s user 0,02s system 99% cpu 0,046 total
HOME=$PWD/antigen zsh -i -c exit  0,04s user 0,01s system 92% cpu 0,060 total
HOME=$PWD/antigen zsh -i -c exit  0,04s user 0,01s system 83% cpu 0,061 total
HOME=$PWD/antigen zsh -i -c exit  0,03s user 0,02s system 96% cpu 0,051 total
HOME=$PWD/antigen zsh -i -c exit  0,03s user 0,01s system 99% cpu 0,044 total
HOME=$PWD/antigen zsh -i -c exit  0,03s user 0,01s system 99% cpu 0,044 total
HOME=$PWD/antigen zsh -i -c exit  0,03s user 0,02s system 98% cpu 0,046 total
HOME=$PWD/antigen zsh -i -c exit  0,03s user 0,01s system 99% cpu 0,044 total
HOME=$PWD/antigen zsh -i -c exit  0,02s user 0,02s system 99% cpu 0,044 total

https://user-images.githubusercontent.com/7953703/179339258-615be9c0-6c11-455f-a0e3-01baed2527d4.mp4

https://user-images.githubusercontent.com/7953703/179339264-22d41e7f-93c0-4194-bcda-584bb85862ed.mp4

avently commented 2 years ago

If you disable lucid mode you'll see youself waiting seconds for Zinit to load (on hardware like notebook I mentioned of course). Which means that loading mechanism could be made better or at least identical with that what antigen uses. After that lucid mode will be faster too automatically. I would consider this idea if it's technically possible while having working other parts of zinit.

vladdoster commented 2 years ago

Using your config

    for snipet in completion clipboard directories spectrum; do
        zinit ice wait lucid
        zinit snippet OMZ::lib/$snipet.zsh
    done
    zinit snippet OMZ::lib/key-bindings.zsh

    zinit ice wait lucid atload"_zsh_autosuggest_start"
    zinit load zsh-users/zsh-autosuggestions

    zinit ice wait lucid
    zinit light zsh-users/zsh-completions

    # No lucid load here
    zinit load zsh-users/zsh-history-substring-search

    zinit ice wait lucid
    zinit load mfaerevaag/wd

    zinit ice wait lucid
    zinit load b4b4r07/enhancd

    zinit ice wait lucid
    zinit load zdharma-continuum/history-search-multi-word

    zinit ice wait lucid
    zinit load jirutka/zsh-shift-select

    zinit ice wait lucid
    zinit load zdharma-continuum/fast-syntax-highlighting

After modifying it to leverage zinit features, I get:

Total: 0.158 sec
ᐳ zi zstatus
Zinit's main directory: /Users/e109082/.local/share/zsh/zinit
Zinit's binary directory: /Users/e109082/.local/share/zsh/zinit/zinit.git
Plugin directory: /Users/e109082/.local/share/zsh/zinit/plugins
Completions directory: /Users/e109082/.local/share/zsh/zinit/completions
Loaded plugins: 14
Light loaded: 13
Downloaded plugins: 13
Enabled completions: 193
Disabled completions: 0
Completions available overall: 196
Snippets loaded: OMZ::plugins/history-substring-search <svn>, OMZL::clipboard.zsh <single file>, OMZL::compfix.zsh <single file>, OMZL::completion.zsh <single file>, OMZL::git.zsh <single file>, OMZL::grep.zsh <single file>, OMZL::key-bindings.zsh <single file>, OMZL::spectrum.zsh <single file>, OMZP::brew <single file>, OMZP::npm <single file>, PZT::modules/helper/init.zsh <single file>, PZT::modules/history <single file>, PZT::modules/rsync <single file>
Compiled plugins: 12
~/.local/share/zsh/zinit
ᐳ zi list
romkatv/zsh-bin
sindresorhus/pure *
zdharma-continuum/zinit-annex-bin-gem-node *
zdharma-continuum/zinit-annex-binary-symlink *
zdharma-continuum/zinit-annex-patch-dl *
zdharma-continuum/zinit-annex-submods *
zsh-users/zsh-completions *
zsh-users/zsh-autosuggestions *
b4b4r07/enhancd *
zdharma-continuum/history-search-multi-word *
zdharma-continuum/fast-syntax-highlighting *
zinit/cleanup *
jirutka/zsh-shift-select *
mfaerevaag/wd *
~/.local/share/zsh/zinit
ᐳ zp
Plugin loading times:
    4 ms - romkatv/zsh-bin
   10 ms - OMZL::clipboard.zsh
    1 ms - OMZL::compfix.zsh
    2 ms - OMZL::completion.zsh
    1 ms - OMZL::git.zsh
    1 ms - OMZL::grep.zsh
    1 ms - OMZL::key-bindings.zsh
    2 ms - OMZL::spectrum.zsh
    1 ms - OMZP::brew
    8 ms - OMZP::npm
    1 ms - PZT::modules/history
    1 ms - PZT::modules/helper/init.zsh
    5 ms - PZT::modules/rsync
   27 ms - sindresorhus/pure
    4 ms - zdharma-continuum/zinit-annex-bin-gem-node
    3 ms - zdharma-continuum/zinit-annex-binary-symlink
    2 ms - zdharma-continuum/zinit-annex-patch-dl
    3 ms - zdharma-continuum/zinit-annex-submods
    7 ms - OMZ::plugins/history-substring-search
    2 ms - zsh-users/zsh-completions
   22 ms - zsh-users/zsh-autosuggestions
   11 ms - b4b4r07/enhancd
    2 ms - zdharma-continuum/history-search-multi-word
   32 ms - zdharma-continuum/fast-syntax-highlighting
    1 ms - zinit/cleanup
    2 ms - jirutka/zsh-shift-select
    2 ms - mfaerevaag/wd
Total: 0.158 sec
vladdoster commented 2 years ago

And it loads OMZ plugins and libs fine

avently commented 2 years ago

You show your results of using zinit, but not the comparison with antigen. So this results doesn't matter because of no comparison and different hardware.

I wrote a test script that do everything to help us to see the difference. Please, if you want to see and to fix the performance problem, use this script with your changes if you like. And we can understand the situation better.