Skip to content
This repository has been archived by the owner on Apr 24, 2020. It is now read-only.

Caching to speed up prompt generation #1170

Closed
romkatv opened this issue Feb 24, 2019 · 33 comments
Closed

Caching to speed up prompt generation #1170

romkatv opened this issue Feb 24, 2019 · 33 comments

Comments

@romkatv
Copy link

romkatv commented Feb 24, 2019

tl;dr: I patched P9K to reduce my zsh prompt drawing latency by over 10x. Is this something you would be interested in adopting?

I recently started using Windows Subsystem for Linux and discovered that my standard Linux zsh environment was so slow, it was barely usable. It was taking over a second to draw a prompt after each command. Granted, it was never snappy even on Linux but it was at least manageable.

I've spent some time profiling and optimizing the code and the results look promising. On each prompt P9K performs a lot of computation and over 90% of it is the same as in the last prompt. I implemented simple caching to avoid recomputing things and now my prompts get rendered in less than 100ms on WSL -- over 10x reduction in latency. They are now also blazingly fast on Linux.

I'm not an expert in zsh, so I didn't want to open a PR right away. I also didn't write any tests. If there is interest in this type of improvements, the code is here: https://github.com/romkatv/powerlevel9k/tree/caching. The code adds a general caching mechanism for anything that prompt generators might want to cache between calls, and then applies it to left_prompt_segment and right_prompt_segment for nice latency reduction across the board. It also contains optimizations for all prompt generators that I personally use and that were showing up on my profile as being slow. Let me know what you want me to do. Open a PR, sign something so that you can pull the code, go away, something else?

P.S.

My .zshrc is here: https://github.com/romkatv/dotfiles-public/blob/master/.zshrc.

@onaforeignshore
Copy link
Contributor

This is a very interesting approach, but are you aware that the whole codebase is being rewritten for 0.7.0? Your functions are based on the master (current) branch, but we are in the process of migrating to the next (0.7.0) branch.

@romkatv
Copy link
Author

romkatv commented Feb 25, 2019

... are you aware that the whole codebase is being rewritten for 0.7.0?

Nope. Didn't know that. I'm open to suggestions for how to proceed. Doing nothing is fine with me, too.

@romkatv
Copy link
Author

romkatv commented Feb 27, 2019

In case anyone is also bothered by how slow the vcs/git prompt is, I've managed to speed it up by a large margin. On Linux my whole prompt (which includes vcs as well as all the prompts I listed in the previous comment) renders in 50ms when I'm in a git repo with 1k files. In a large repo such as Linux kernel, it renders in 300ms -- too slow for my taste. I added an option to disable scanning dirty files for repos above certain size and set it at 4k files in my .zshrc. With this option my prompt renders in 150ms when in Linux repo. The prompt also uses color-coding to signal that it didn't scan for dirty files. Finally vcs prompt is fast enough to be usable for me!

The trick was to write a custom C binary that prints everything we need to know about a git repo. It's much faster than calling git multiple times, which spawns a dozen processes with accompanying pipes and repeats many actions unnecessarily -- such as scanning parent folders in search of .git. And also caching, of course, to make rendering itself fast. The C code is in https://github.com/romkatv/gitstatus. The ZSH code is in the same branch as caching: https://github.com/romkatv/powerlevel9k/tree/caching.

If anyone wants to give it a try with their own master-based setup (especially if it's sluggish), here's a non-committal way to do it.

# Enable caching of parts of the prompt to make rendering much faster.
POWERLEVEL9K_USE_CACHE=true
# Enable alternative implementation for the vcs prompt. It's much faster but it only supports git.
# Tell it to not scan for dirty files in repos with over 4k files.
POWERLEVEL9K_VCS_STATUS_COMMAND="/tmp/gitstatus --dirty-max-index-size=4096"
wget https://github.com/romkatv/gitstatus/releases/latest/download/gitstatus -P /tmp
chmod +x /tmp/gitstatus
# Adjust this path depending on where you normally source powerlevel9k.zsh-theme from.
POWERLEVEL9K_INSTALLATION_DIR=~/.oh-my-zsh/custom/themes/powerlevel9k
source <(curl -f https://raw.githubusercontent.com/romkatv/powerlevel9k/caching/powerlevel9k.zsh-theme)

Then see if your current shell feels more responsive. No permanent changes are done to your setup, so once you exit zsh you are back to business as usual.

I can vouch for the following prompts being fast in the patched version:

  • root_indicator
  • dir_writable
  • dir
  • status
  • command_execution_time
  • background_jobs
  • time
  • vcs

This was referenced Feb 27, 2019
@dritter
Copy link
Member

dritter commented Feb 27, 2019

Hi @romkatv !
This is very interesting and super impressive results you got. It is true that we depend crucially on IO performance. This is especially a pain on WSL or inside VMs.
TBH I am a bit ambiguous about the caching, because there are a lot of external influences that could/should lead to cache invalidation that we cannot control. In case of the dir segment, which is good cachable at the first glimpse (chpwd hook), there are truncation strategies that depend on a unique path. So, if another folder was created that starts with the same characters, without changing the folder, the cache would be stale..
This is a pretty weak example, but my point is the more the command depends on externals, the less cachable is the result.
But you found an awesome "workaround" (holy moly, you've written a whole C++ lib) for the vcs (well, at least for the git part) segment. Have you considered upstreaming this either to git directly (I always wondered why there is no circuit breaker for git status when the first untracked file was found) or to zsh (as a replacement for VCS_INFO)?

@bhilburn Would we add a binary to P9K to replace VCS_INFO? And that needs to work on all major OSes..

Edit: By upstreaming to git I meant the concept obviously. Having a single command that outputs machine-readable information as fast as possible. Of course there is git status --porcelain, but we need a lot more information that that.

@romkatv
Copy link
Author

romkatv commented Feb 27, 2019

TBH I am a bit ambiguous about the caching, because there are a lot of external influences that could/should lead to cache invalidation that we cannot control.

This is implemented in a safe way. The data we pull from the cache is never stale. Every entry in the cache is immutable and it never becomes invalid. Here's how it works. Every time we need to draw a vcs prompt, we call gitstatus. It might print something like this (10 values, each on its line):

"master"
"master"
"git@github.com:romkatv/gitstatus.git"
""
1
1
0
3
0
2

(The meaning of each line is documented at powerlevel9k.zsh-theme).

From this we can assemble the vcs prompt. It doesn't depend on any other data such as $PWD, time of the day or anything else (if it did depend on any of the above, we would add them to the cache key). Once we assemble the prompt, we can save it for the future. The key in the cache is the ten lines that gitstatus gave us. The next time we call gitstatus, it's likely to give us the same 10 lines of data because the state of a repository rarely changes (at least the part of the state that affects the prompt). We find the fully formatted prompt that corresponds to this data in the cache -- with all icons and colors already resolved -- and display it instantly.

So we have two things: fast way to get the git state, and then a fast way to format that data as a prompt. The first is fast because C, the second is fast because caching.

I use the same technique for printing other prompts, such as dir. The input data for dir is the directory path, so the cache contains things like "/home/romka" => <formatted dir segment, with icons colors and all>. Whenever I'm in "/home/romka", the segment can be looked up and printed in no time. It's always valid for this directory.

Likewise for status segment. Its key is the error code of the command. For error code 0 the segment always looks the same (green checkbox on grey background for me), so we can cache it. Likewise for error code 1, 2 and so on.

Have you considered upstreaming this either to git directly (I always wondered why there is no circuit breaker for git status when the first untracked file was found) or to zsh (as a replacement for VCS_INFO)?

Not really. This is a larger commitment than I can afford.

FWIW, I did try to make it more-or-less generic in p9k. It's possible to ditch vcs_info in p9k in favor of much simpler model. You can see in the code that I added POWERLEVEL9K_VCS_STATUS_COMMAND. This parameter specifies the command that is supposed to print the ten lines. prompt_vcs can then render the prompt with very little effort, thanks to the data being in exactly the format it needs.

By default, POWERLEVEL9K_VCS_STATUS_COMMAND could point to a function that generates the ten lines by calling git: git rev-parse --abbrev-ref HEAD to print the current branch, git rev-list --walk-reflogs --count refs/stash to get the number of stashes, git diff-index --cached --quiet --ignore-submodules=dirty HEAD to check for staged files, and so on.

Users could override POWERLEVEL9K_VCS_STATUS_COMMAND for better performance (e.g., by using my binary, or even writing something faster). However, I think even without it the prompt will be much faster than with vcs_info, simply because there would be so much less zsh involved in massaging the data.

It's also possible to use vcs_info to produce the 10 lines in the required format. This gives us a fallback for vcs backends other than git. I didn't implement this because I don't work with non-git repos.

@docwhat
Copy link
Contributor

docwhat commented Feb 28, 2019

I'm concerned that your gitstatus tool isn't cross platform. Some platforms that should be covered include macOS, ppc64le Linux, the various arms, the bsds, etc.

I have thought of doing something similar using golang (which is great for cross compiling) but my git-internals-fu isn't that strong.

Caching the work that ZSH is doing to build the actual prompt (symbols, colors, etc.) shouldn't be taking so long that caching it speeds it up my 10x. If it is, then we should fix the ZSH code.

@Syphdias
Copy link
Member

Just my two cents, I think it's a great idea and it would synergize really well with making the prompt asynchronous (insert fitting issue here). Show the old prompt from the cache and update to the current values if ready. With a synchronous prompt it has its drawback, I agree.

@romkatv
Copy link
Author

romkatv commented Feb 28, 2019

I'm concerned that your gitstatus tool isn't cross platform.

That's a valid concern. In theory it can be as cross-platform as libgit2, which officially supports all major platforms. Getting there isn't difficult but it's work nonetheless. Ideally, I'd love to see p9k having a configurable provider of vcs status information so that users who care about the responsiveness of their shell (like myself) could plug in their (potentially platform-specific) implementation without having to rewrite prompt formatting code in p9k. Users who don't care could use the most portable default implementation (like vcs_info). This is roughly what I've attempted to sketch in my patch.

Caching the work that ZSH is doing to build the actual prompt (symbols, colors, etc.) shouldn't be taking so long that caching it speeds it up my 10x. If it is, then we should fix the ZSH code.

Indeed. I was surprised when my improvised profiler had pointed to the formatting code as the primary CPU hog in p9k. Having replaced a large chunk of p9k with more efficient code, and having added caching, I've confirmed that indeed formatting is a major cause of prompt latency.

Consider the following trivial prompt function:

prompt_greet() {
  if [[ -n $POWERLEVEL9K_GREETING ]]; then
    $1_prompt_segment $0 $2 green black $POWERLEVEL9K_GREETING LINUX_ICON
  fi
}

If POWERLEVEL9K_GREETING is not empty, this prompt segment will display it with a Linux icon next to it. It's as simple as it gets. No user overrides to change colors or icons or anything fancy like that.

When I add this prompt to POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS and type POWERLEVEL9K_GREETING=hi, prompt_greet generates the following string:

 %f%F{002}<%f%K{002}%F{000} hi%F{000} @

(I've replaced the Linux icon with @ to make it readable.)

We can see the "hi" message surrounded by some fluff. In order to produce this string, p9k executed 120 lines of code. That's a lot of code for such a simple segment. The same 120 lines will execute on every prompt.

If we run the same experiment with the patched version of p9k from https://github.com/romkatv/powerlevel9k/tree/caching, we get 58 lines on the first drawing of the prompt--half of the original--and just 11 lines on subsequent prompts. If you look carefully at the last trace, you'll notice that it says "bye" rather than "hi". And yet, it has hit the cache. This is because p9k has cached the formatting fluff but the dynamic content isn't in the cache. Function prompt_greet will generate its output with 11 lines of code for every prompt after the first one even if we keep changing POWERLEVEL9K_GREETING.

Here are the 11 lines, annotated:

# Should we join this segment with the previous?  This is a function call.
_p9k_should_join_right 4
    [[ 2 -ge 4 ]]
local join=false

# The cache key incorporates everything that affects the formatting of the segment.
# Note the lack of "hi" or "bye" in it.
local cache_key='right_prompt_segment prompt_greet green black LINUX_ICON 008 false'

# Check if we have the formatting fluff in the cache. This is a function call.
_p9k_cache_get 'right_prompt_segment prompt_greet green black LINUX_ICON 008 false'
    _P9K_RETVAL=\''%F{002}<%K{002} %F{000}'\'' '\''002'\'' '\''%F{000}@ '\' 
    [[ \''%F{002}<%K{002} %F{000}'\'' '\''002'\'' '\''%F{000}@ '\' != __p9k_empty__ ]]

# Cache hit! We've retrieved the formatting fluff from the cache.
local tuple=( '%F{002}<%K{002} %F{000}' 002 '%F{000}@ ' )

# Splice the dynamic content into the formatting string and print the prompt.
echo -n '%F{002}<%K{002} %F{000}bye %F{000}@ '

# Update the environment so that the next segment knows how to print itself.
CURRENT_BG=002
LAST_SEGMENT_INDEX=4

The difference in performance is immediately apparently when you try it. Even if your prompt latency feels OK now, you'll still notice the improvement.

I'm happy to keep using my own patched version with a custom C binary. Anyone else is welcome to try it. If you want to use any ideas or code in p9k, go ahead and copy them.

@romkatv
Copy link
Author

romkatv commented Feb 28, 2019

I think it's a great idea and it would synergize really well with making the prompt asynchronous (insert fitting issue here). Show the old prompt from the cache and update to the current values if ready.

Thanks, Syphdias.

I just want to clarify that the cache I implemented never gives you wrong results. It's a pure optimization that never affects what actually gets printed. The only impact it has is that printing happens much faster, and memory usage is a bit higher. [1]

Even though the git prompt I now have is an order of magnitude faster than the stock one, it produces the same results. [2]

[1] This isn't exactly true. With the official p9k you can set POWERLEVEL9K_TIME_FOREGROUND=red in an interactive shell and the next prompt will have time prompt segment printed in red. My version doesn't pick up live configuration changes (FWIW, the official p9k doesn't pick up all live config changes either; my version just picks up even fewer). But it always, 100%, picks up dynamic environment changes. It never displays wrong or stale data in the prompt.

[2] This is also not exactly true. My gitstatus doesn't support a few features that the official vcs_info-based prompt supports. For example, it never prints tags. This is easily fixable. If anything, the approach with a C binary is much more flexible. You have more freedom w.r.t. what information you extract from git repos and you get to use a decent API instead of solving command-line flag puzzles.

@docwhat
Copy link
Contributor

docwhat commented Feb 28, 2019

120 lines of code

A quick look at the code doesn't show much that should be slow. It is all tests ([[ ]]) and string manipulation.

Another question: Are you using ZSH compiling?

Basically, those lines of code should be very fast and if they aren't we should delve into what's being slow and fix it before we start optimizing via caching.

The async stuff is fixing specific known problems and will speed up the VCS segment.

@romkatv
Copy link
Author

romkatv commented Feb 28, 2019

A quick look at the code doesn't show much that should be slow. It is all tests ([[ ]]) and string manipulation.

No, I'm not. Didn't know such a thing existed. Sounds exciting! What's the right way to enable ZSH compilation for p9k? I'm using oh-my-zsh if that's relevant.

Basically, those lines of code should be very fast and if they aren't we should delve into what's being slow and fix it before we start optimizing via caching.

FWIW, here's trace comparison for prompt_vcs in a git repo: https://gist.github.com/romkatv/5ab160354e69f201a23a33665e674f78. 738 lines vs 19. I believe the original code has called git 15 times and made 20+ file reads directly from .git.

@docwhat
Copy link
Contributor

docwhat commented Feb 28, 2019

The magic words to search for are zcompinit and zcompile.

@docwhat
Copy link
Contributor

docwhat commented Feb 28, 2019

Basically, those lines of code should be very fast and if they aren't we should delve into what's being slow and fix it before we start optimizing via caching.

FWIW, here's trace comparison for prompt_vcs in a git repo: https://gist.github.com/romkatv/5ab160354e69f201a23a33665e674f78. 738 lines vs 19. I believe the original code has called git 15 times and made 20+ file reads directly from .git.

Oh, I'm not arguing that vcs_info is fast... it is correct but it isn't fast. The async branch (which will in effect have caching since it will only change when it needs to) will address that particular issue.

@romkatv
Copy link
Author

romkatv commented Feb 28, 2019

The magic words to search for are zcompinit and zcompile.

Mysterious at the very least. Google search for "zcompinit zcompile" (without quotes) shows a total of 2 results, neither of which are enlightening. I even though something is wrong with Google and tried Bing. A lone result. Just one.

Are there some instructions I can follow to enable zsh compilation for p9k prompt? Is it common knowledge that without such compilation p9k is slow but with compilation it's fast?

@dritter
Copy link
Member

dritter commented Feb 28, 2019

I am still busy with finishing up v0.6.7 and preparing v0.7.0, so I would plan such things for Version v0.8.0 (which isn't that far away).

The async stuff is fixing specific known problems and will speed up the VCS segment.

That is what I am currently preparing (again.. 🙄 ). The PR to come adds async functionality to segments and has a cache as well (but not as sophisticated as seen here)..

Caching the work that ZSH is doing to build the actual prompt (symbols, colors, etc.) shouldn't be taking so long that caching it speeds it up my 10x. If it is, then we should fix the ZSH code.

VCS_INFO could benefit from some caching as well. I agree with @docwhat that we should fix the VCS_INFO code in the first place. There are some things in our vcs code that I wanted to upstream to VCS_INFO for a long time now (like reading out the stashes). That would benefit all users of VCS_INFO.

I'm concerned that your gitstatus tool isn't cross platform. Some platforms that should be covered include macOS, ppc64le Linux, the various arms, the bsds, etc.

This could be done by using a rust implementation of git2. @ryanwhocodes uses this in his port of Powerlevel9k, rustlevel9k.

Are there some instructions I can follow to enable zsh compilation for p9k prompt? Is it common knowledge that without such compilation p9k is slow but with compilation it's fast?

I think it is not very common knowledge.. That would make a great add on to our documentation.
You can find general information about zcompile in the ZSH docs (search for zcompile).

@romkatv
Copy link
Author

romkatv commented Mar 1, 2019

I've optimized my C binary that talks to git and see a nice additional drop in latency. The code is a bit messy (didn't have time to clean it up) but it works. My prompt renders in 200ms in Linux kernel git repo with all vcs bells and whistles turned on, including dirty files scanning. In nerd-fonts (a fairly large repo with 4k files) my prompt renders in 70ms. This is again with dirty files scanning and all. In a small repo prompt renders in 30ms.

I still haven't tried ZSH compiling. Will give it a shot when I'll have free time.

@docwhat
Copy link
Contributor

docwhat commented Mar 1, 2019

@romkatv Just for you, I whipped something together using zcompile. It does have a noticeable improvement to the prompt speed (e.g., hitting return rapidly a bunch of times).

I've done C cross compiling before and it is a real pain to do. What do you think about using golang instead. I'm willing to whip up the build infrastructure.

Here is the the pure golang git library.

https://github.com/docwhat/dotfiles/blob/master/local/libexec/tools-update/zsh

@romkatv
Copy link
Author

romkatv commented Mar 1, 2019

@romkatv Just for you, I whipped something together using zcompile.

@docwhat Did you mean to link to your code/doc? Where can I find out what you've whipped together?

I searched for zcompile in your https://github.com/docwhat/dotfiles. I see a call in zlogin to compile compinit, which isn't what I'm after. The only other occurrence is a commit from Feb 28. Is this the file you wanted to show me? How can I use it?

By the way, is it actually true that it's common knowledge that one must use zcompile to optimize prompt rendering time? @dritter says yes, but his dotfiles don't mention zcompile. I'm also surprised that Google doesn't return any blog posts, StackOverflow questions or installation guides that say how to use zcompile to speed up prompt. None of the popular zsh frameworks have compilation by default or as an option. Given how easy it is to find complains about slow prompts in zsh (dozens just on https://github.com/bhilburn/powerlevel9k/), this lack of awareness of the apparent solution seem surprising.

Here is the the pure golang git library.

We live in different worlds. For me a suggestion to port C code to Go probably sounds as bizarre and baffling as the reverse would sound to you.

@romkatv
Copy link
Author

romkatv commented Mar 1, 2019

Many of you have dotfiles in public repositories on github. Can anyone point me to a config you use where enabling or disabling zcompile affects prompt latency? Not just loading time but latency of rendering the prompt when you press Enter. After some time researching this subject I'm inclined to believe this isn't possible. I'd be glad to be proven wrong as I'll take anything that will make my shell speedier.

@docwhat
Copy link
Contributor

docwhat commented Mar 2, 2019

@romkatv
Copy link
Author

romkatv commented Mar 2, 2019

@docwhat You mentioned that zcompile has "a noticeable improvement to the prompt speed (e.g., hitting [return] rapidly a bunch of times)" and kindly provided the code with which this improvement was achieved (https://github.com/docwhat/dotfiles/blob/master/local/libexec/tools-update/zsh). I tried to reproduce your results.

First of all, we need to define what we are measuring. What I'm after is the time it takes for prompt to appear after you press [ENTER]. Roughly speaking, if you press and hold [ENTER], how many prompts will be printed per second? I wrote zsh-prompt-benchmark to automate this kind of measurement and to remove subjectivity.

I measured the prompt timing with Powerlevel9k with the default setup (no zcompile). Then I compiled all Powerlevel9k files with the following command:

for f in ~/.oh-my-zsh/custom/themes/powerlevel9k/{powerlevel9k.zsh-theme,functions/*}; do
  zcompile $f && echo ok $f || echo error $f;
done

I've verified that a .zwc file has appeared next to powerlevel9k.zsh-theme and to all files under functions. I then restarted zsh and measured prompt latency once again. There was no difference.

Am I doing something wrong? Can anyone confirm that it's possible to speed up prompt by using zcompile? Please benchmark your prompt with and without zcompile and if there is a difference, please do tell how you used zcompile.

According to the documentation (and common sense), zcompile only affects sourcing. So if starting an interactive shell takes a long time, you might benefit from zcompile but it shouldn't speed up function execution. I'm far from being an expert in zsh though, so please do point our where I'm wrong.

FYI, I've renamed my fork to Powerlevel10k because it seems unlikely that my changes are going to be upstreamed. I made it clear that Powerlevel10k is a fork of Powerlevel9k but I wanted to use a separate name to be able to refer to my code easily. I wrote decent documentation and included benchmarks comparing Powerlevel10k to Powerlevel9k, both master and next branches. I urge you to take a look: https://github.com/romkatv/powerlevel10k#how-fast-is-it. Here's the summary:

Powerlevel10k with gitstatus renders prompt about 10 times faster than powerlevel9k/master (stable version) and about 5 times faster than powerlevel9k/next (beta version). Powerlevel10k is faster than Powerlevel9k even without gitstatus but the difference isn't as dramatic.

It bears repeating that Powerlevel10k achieves this performance without sacrificing functionality. The prompts it displays are always the same as in powerlevel9k/master.

@dritter
Copy link
Member

dritter commented Mar 6, 2019

Btw. I wanted to clarify that we are not against integrating caching or gitstatus. Speed is always a good thing. So we should talk more about how. As gitstatus is not a full replacement for VCS_INFO and requires a bit more setup, I suggest we put this into a new Segment based on the next branch. This way people can decide for themselves.
The caching part is also interesting. This could be integrated based on #1176 (which is still a bit raw ATM).

@romkatv
Copy link
Author

romkatv commented Mar 6, 2019

I'll be happy to collaborate on integrating gitstatus with Powerlevel9k. Take a look at how I dit it with robobenklein/p10k in robobenklein/zinc#2. I think this approach could work well for Powerlevel9k, too.

I modified the existing vcs segment to do the following:

backends := user_defined_vcs_backends
if (backends contains git && gitstatus is available) {
  if (git repo) {
    use gitstatus
    return
  } else {
    backends := backends without git
  }
}
if (backends is not empty) {
  use vcs_info for backends
}

By default user_defined_vcs_backends is set to git svn hg. Users can override it in their configs. For example, if they use neither svn nor hg (like myself), they can set user_defined_vcs_backends=git and avoid extra latency from vcs_info altogether.

This provides a nice fallback for systems where gitstatus doesn't work or isn't running for some other reason. It also allows us to support all backends that vcs_info supports while still having low latency prompts in git repos.

@romkatv
Copy link
Author

romkatv commented Mar 7, 2019

By the way, for those of you who don't follow /r/zsh, Powerlevel10k now works on all major platforms (Mac, Linux, FreeBSD and WSL). It's backward-compatible with Powerlevel9k configuration and it's 50 times faster.

If you are currently using Powerlevel9k, type this and see how fast your shell will become while still looking the same:

git clone https://github.com/romkatv/powerlevel10k.git /tmp/powerlevel10k
source /tmp/powerlevel10k/powerlevel10k.zsh-theme

(When you are done playing, rm -rf /tmp/powerlevel10k and exit zsh.)

You can find other options for trying out the theme in the docs.

@bhilburn
Copy link
Member

Hey all - Sorry I'm so late jumping in, here. I've been following this conversation by e-mail (I get an e-mail for every single comment that gets posted for p9k, and I read every single one of them, hah), and in Gitter.

@romkatv - Clearly, your experiment in compiled code & caching has resulted in some pretty serious gains. That's fantastic!

We've been chatting about this in Gitter, and we are quite serious about getting your work upstreamed. There are a few key things that we want to be sure of in the process:

  • That it works on all supported platforms (it looks like you just sorted that one out).
  • We avoid additional dependencies wherever possible, and if we have to use them, we try to include them to make installation painless (see the approach from async libs).
  • Keep installation & configuration as simple as possible (most of our issue reports are still about this). So, if something needs to be compiled after it's configured, for example, we need to make sure that's a clean UX.

If possible, we will also try to upstream any improvements we make to VCS_INFO. That's not guaranteed, for a lot of reasons, but it's worth a shot. I don't want to hold up P9k development for it, but I also don't want to carry patchsets.

@romkatv - Can you work with the development team in #1185 to get your stuff upstreamed? I think the whole community will benefit from the work you've done.

I just tried merging your branch into our master to see what it would look like, and the only conflicts appear to be in docs. That said, it does look like you've deleted all of the tests and testing infrastructure in your master, so a straight merge won't work. Based on the changeset, though, my guess is that everything you've done is fairly well contained in gitstatus/? If so, it should be pretty straightforward in terms of code organization.

Separately, you're obviously welcome to do whatever you like in terms of the code and P10k, but I would encourage you to work closely with us to get your work upstreamed rather than splitting the community.

Looking forward to seeing the progress in #1185. I'm not sure if you've looked at next, yet, but a ton of work has gone into it over the last year, and it's going to be a huge upgrade for the project.

@romkatv
Copy link
Author

romkatv commented Mar 12, 2019

We avoid additional dependencies wherever possible, and if we have to use them, we try to include them to make installation painless (see the approach from async libs).
Keep installation & configuration as simple as possible (most of our issue reports are still about this). So, if something needs to be compiled after it's configured, for example, we need to make sure that's a clean UX.

I'm guessing you haven't read https://github.com/romkatv/powerlevel10k and haven't tried the theme. It's identical to Powerlevel9k in terms of installation and configuration. If you replace the content of your powerlevel9k directory with that of Powerlevel10k and restart zsh, your prompt will look the same as before (assuming you are using powerlevel9k/master or have configuration that is compatible with it). You can even source Powerlevel10k from an interactive shell that is currently using Powerlevel9k and everything will become faster without any other changes.

If possible, we will also try to upstream any improvements we make to VCS_INFO.

This would be great.

Can you work with the development team in #1185 to get your stuff upstreamed? I think the whole community will benefit from the work you've done.

I'm trying to, but it's pretty discouraging that my comments get ignored both here and there. I see what appears to be unsound technical judgement, attempt to engage in conversation and never get a reply. Misleading statements that waste my time don't get followed up with any sort of an apology or acknowledgement of mistake (zsh compilation reduces prompt latency in Powerlevel9k? really?). It's unclear whether anyone from the dev has even looked at the docs or code, or tried the theme. This isn't the first open source project I'm contributing to, so I'm well aware of the differences in project cultures. So far my experience with powerlevel9k has been underwhelming. Hopefully it'll improve. For an example of a good contributor experience see my comment in libgit2 and the replies below. That's the attitude that makes people want to contribute to your project.

I just tried merging your branch into our master to see what it would look like, and the only conflicts appear to be in docs.

I'm pulling changes from Powerlevel9k. When you attempt to merge, there are no conflicts because I've already resolved them.

Conflicts in README.md are because I've a completely different documentation. Think of it as an independent file that isn't related to README.md in Powerlevel9k. It defers to Powerlevel9k for configuration and installation options and only explains how Powerlevel10k is different.

That said, it does look like you've deleted all of the tests and testing infrastructure in your master...

Indeed. I deleted everything I don't use to avoid misleading users and to have have fewer upstream changes to merge.

Based on the changeset, though, my guess is that everything you've done is fairly well contained in gitstatus/?

I've changed almost every line of code that gets executed when prompt is rendered with my settings (I haven't touched the prompts I don't use though). Have you seen the benchmarks? Powerlevel10k renders prompt in my root directory in 1ms, compared to 101ms for powerlevel9k/master and 26ms for powerlevel9k/next. My root directory isn't a git repo, so the difference isn't due to gitstatus.

I would encourage you to work closely with us to get your work upstreamed rather than splitting the community.

What do you mean by splitting the community? Powerlevel10k renders the same prompt with the same configuration options as Powerlevel9k, the only difference being performance. It's essentially the same theme with two implementations. Users can freely switch back and forth between the two implementations and exchange configuration profiles without worrying about which implementation others use.

I'm not sure if you've looked at next, yet, but a ton of work has gone into it over the last year, and it's going to be a huge upgrade for the project.

I've only used it when benchmarking. What are the biggest improvements that you are looking forward to bringing to your users?

@bhilburn
Copy link
Member

bhilburn commented Mar 12, 2019

Hi @romkatv -

I'm guessing you haven't read https://github.com/romkatv/powerlevel10k and haven't tried the theme. It's identical to Powerlevel9k in terms of installation and configuration.

I wasn't providing those items to accuse you of having done something wrong, or saying that you hadn't done them. I was merely telling you what we care about, and the kinds of things we consider during any major feature upstream. It sounds like these likely aren't a concern for you work, which is great!

I'm trying to, but it's pretty discouraging that my comments get ignored both here and there.

I haven't looked for a response to every one of your comments, but at cursary glance, it seems like you are getting quick responses to everything you post?

I see what appears to be unsound technical judgement, attempt to engage in conversation and never get a reply. Misleading statements that waste my time don't get followed up with any sort of an apology or acknowledgement of mistake (zsh compilation reduces prompt latency in Powerlevel9k? really?).

I'll address the second one first - my guess is that any misleading statements were made either due to misunderstanding or by mistake. I haven't seen such statements, but if you disagree or feel that you have been insulted in any way, then I encourage you to specifically point me to the relevant posts. If you aren't comfortable doing it publicly, then you're welcome to e-mail me privately.

To address your first comment, accusations of unsound technical judgement are neither constructive nor conducive to good collaboration. If you disagree with a technical decision that has been made regarding your work, then please raise it directly with me. You can do that here, in Gitter, or by e-mail.

I've not seen any evidence of the things you are accusing the P9k community about. As I said above, if you feel strongly that your involvement with the development community has been mishandled in some way, please point me to specific examples. Otherwise, please step down from your rather dramatic accusations. You've received significant time investment from the P9k devs both in this issue as well as in #1185, and we are eager to work with you.

I'm pulling changes from Powerlevel9k. When you attempt to merge, there are no conflicts because I've already resolved them.

Great! Thanks for maintaining upstream compatibility. That will make things much easier, obviously.

That said, it does look like you've deleted all of the tests and testing infrastructure in your master...

Indeed. I deleted everything I don't use to avoid misleading users and to have have fewer upstream changes to merge.

Makes sense.

Based on the changeset, though, my guess is that everything you've done is fairly well contained in gitstatus/?

I've changed almost every line of code that gets executed when prompt is rendered with my settings (I haven't touched the prompts I don't use though). Have you seen the benchmarks? Powerlevel10k renders prompt in my root directory in 1ms, compared to 101ms for powerlevel9k/master and 26ms for powerlevel9k/next. My root directory isn't a git repo, so the difference isn't due to gitstatus.

Yes, I've seen the benchmarks - hence my comments about how impressive the results are.

I would encourage you to work closely with us to get your work upstreamed rather than splitting the community.

What do you mean by splitting the community? Powerlevel10k renders the same prompt with the same configuration options as Powerlevel9k, the only difference being performance. It's essentially the same theme with two implementations. Users can freely switch back and forth between the two implementations and exchange configuration profiles without worrying about which implementation others use.

A FOSS community doesn't hinge solely around workflow. If gitstatus doesn't get upstreamed, for whatever reason, the community will be split over the repositories as docs, issues, PRs, and discussions split between them.

I'm not sure if you've looked at next, yet, but a ton of work has gone into it over the last year, and it's going to be a huge upgrade for the project.

I've only used it when benchmarking. What are the biggest improvements that you are looking forward to bringing to your users?

There are significant performance improvements in most parts of the codebase, it's been completely re-organized to make it much simpler to write new segments, much more of the prompt is "configured" at initialization so that there is less runtime work, and lot of the segments have new features based on all of the above. We're pretty excited about it.

@Syphdias
Copy link
Member

I watched this topic from afar (most of the time) since I didn't dive deeper into the details and didn't (and probably still don't) fully understand how your code works. I'd say I am not a programmer but more of a scripter if that makes any sense.

A couple of things I noticed:
@romkatv, you said that you are "not an expert in zsh". I don't think any of "us" (people who recently worked on p9k) would call themselves experts on zsh. You probably know more about zsh in some regards and less in others compared to "us". (Probably in every regard, in regards to myself.)

I see what appears to be unsound technical judgement, attempt to engage in conversation and never get a reply. Misleading statements that waste my time don't get followed up with any sort of an apology or acknowledgement of mistake (zsh compilation reduces prompt latency in Powerlevel9k? really?).

You are very quick, whether it is writing code, researching something or responding. I think, this might be the reason why you felt, that conversation was going slowly. This makes your decision to fork very understandable, imho. Furthermore, I think you are referring to three statements from this thread

  1. "zcompile improves prompt render"
  2. port C to GO
  3. Caching leads to outdated/incorrect prompt and it's not that much faster

With my little knowledge, I think you are probably right about 1 (but you already know that) but you expected some kind of acknowledgement, which I can totally understand, I like to be right as well. 😄
For 2: I have not idea about C and GO, but it also struck me as weird to port something from C to Go. But maybe C cross-compiling is hell and GO cross-compiling is way easier. 🤷‍♂️ I can't judge and is it really important? If you split it from the project and make it easily integrable, I don't see a reason to not have both versions exists.
For 3: I think (and for me this was definitely the case) there was a big misunderstanding how the caching worked and why it is faster. You explained it quite well here and here. And I think you have proven beyond a doubt that the cache makes rendering much faster (even if it has small caveats, also discussed in #817 btw). Your benchmarking proves very useful here! b4ace4e includes it for better performance debugging.

I would love to get the performance boost for p9k and still have people who expand the feature of p9k. I don't think you can (or rather want to) maintain powerlevel10k with pulling from upstream every now and then. Especially the merge from current next to master looks like a lot of work (to me at least) since the code has been restructured/moved a lot.
It would be great to have someone like you who really cares about performance without compromising functionality work more closely with the project but I can understand if this is not what you want.

TL;DR: I hope the bad start you had with this community didn't turn you off too much. 😄

@bhilburn
Copy link
Member

Thanks for adding your thoughts, @Syphdias.

@romkatv - If what @Syphdias accurately reflects your experience, then I do want to be clear that a slow response time is not indicative of disinterest. Realistically, P9k has hundreds of thousands of users, and we have (at best) a handful of core developers. We are inundated with issues and PRs on a daily basis, are trying to keep development moving, and this is just a hobby for us - we all have day jobs. In short, this is the all-too-typical story of a successful F/OSS project.

As @Syphdias said, we would very clearly welcome your involvement and participation :)

@romkatv
Copy link
Author

romkatv commented Mar 13, 2019

@Syphdias You are very perceptive. I appreciate your comment.

@romkatv
Copy link
Author

romkatv commented Mar 25, 2019

I opened this issue to initiate a discussion. Since it has apparently concluded, I'm closing it.

@romkatv romkatv closed this as completed Mar 25, 2019
@resynth1943
Copy link

So... your changes are going to stay in Powerline10K for now?

@romkatv
Copy link
Author

romkatv commented Oct 8, 2019

So... your changes are going to stay in Powerline10K for now?

Changes that I've proposed on this issue no longer exist in their original form. Powerlevel10k has many changes compared to powerlevel9k: some of them can be though of as an evolution of what'd been discussed here, most are unrelated. @dritter has implemented in powerlevel9k some ideas from powerlevel10k (e.g., gitstatusd integration) and cherry-picked some commits (mostly bug fixes; powerlevel10k has bug fixes for all bugs from powerlevel9k issue tracker, with some caveats). I don't intend to send PRs to powerlevel9k, which I've made clear several times in the past to avoid false expectations. I cannot speak for powerlevel9k devs about their plans.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants