zdharma-continuum / fast-syntax-highlighting

Feature-rich syntax highlighting for ZSH
BSD 3-Clause "New" or "Revised" License
1.07k stars 76 forks source link

Very low speed on WSL2 #13

Closed ghost closed 2 years ago

ghost commented 2 years ago

After installing the plugin typing in the shell became very slow. There is a delay after each typed letter. zsh-syntax-highlighting has the same issue.

Details:

jcwillox commented 2 years ago

Yeah, I have the same issue particularly with large blocks of code. This type of issue is actually pretty common with WSL, and it usually comes back to path lookups, by default (you can disable it) the windows system path is added to WSLs $PATH, this adds effectively a networked drive with several folders containing a large number of files, this drastically slows down PATH lookups. Often a simple solution is to remove all folders starting with /mnt/c from the path when the user is running WSL (can check for WSL_DISTRO_NAME), for programs that do not need to search windows paths.

This is a little bash snippet to remove the slow windows paths, not sure how useful it will be in the context of this script, but removing those paths does fix the speed.

PATH=$(echo $PATH | sed s/:/\\n/g | grep -v '/mnt/c' | sed ':a;N;$!ba;s/\n/:/g')
ghost commented 2 years ago

Thank you for your reply and sorry for noticing so late. Will defenitely try this and tell you about the result when I have some free time.

ghost commented 2 years ago

Thanks! It helped!

jcwillox commented 2 years ago

Great, but that was really just an example, WSL actually has a built-in option to disable adding windows PATHs to WSL's PATH, but this isn't really ideal as accessing windows executables via PATH is often useful. Ideally, this would be built into fast-syntax-highlighting somehow.

I suppose an alternative for the end-user is to disable adding windows PATHs and instead to use a whitelist approach and create aliases pointing to the windows executables that you want to access. A benefit of this approach is that it would solve the slow path issue for all affected applications.

xxnuo commented 2 years ago

Great, but that was really just an example, WSL actually has a built-in option to disable adding windows PATHs to WSL's PATH, but this isn't really ideal as accessing windows executables via PATH is often useful. Ideally, this would be built into fast-syntax-highlighting somehow.

I suppose an alternative for the end-user is to disable adding windows PATHs and instead to use a whitelist approach and create aliases pointing to the windows executables that you want to access. A benefit of this approach is that it would solve the slow path issue for all affected applications.

Can you talk about how to disable it? I also encountered this problem on wsl2.

strawhat-dev commented 2 years ago

@BigTear

In /etc/wsl.conf (create if it doesn't exist) add:

[interop]
appendWindowsPath=false

Afterwards run wsl --shutdown and open a new session for the changes to take effect. Note that this will mean Windows executables are no longer in your PATH, e.g., commands like code will no longer work. I think this is better anyway bc it unclutters your WSL PATH and could prevent any problems arising from using the Windows version of something accidentally when you meant to use the Linux version. However, you will manually need to re-add all the Windows executables you care about, like code either:

by creating an alias for the executable

alias code="/mnt/c/[your vscode installation directory]/bin/code"

or by creating a new script that redirects code to the executable

#!/usr/bin/env bash

/mnt/c/[your vscode installation directory]/bin/code "$@"

Also if you do that latter, remember you need to run chmod +x on it and make it available in your PATH for it to be executable from anywhere.

e.g.

# assuming "$HOME/.local/bin" exists and is on your PATH...
echo -e '#!/usr/bin/env bash\n/mnt/c/[your vscode installation directory]/bin/code "$@"' > "$HOME/.local/bin/code"
chmod +x "$HOME/.local/bin/code"

You could also just re-add the executable directory to your PATH variable, but I think that defeats the purpose of cleaning /mnt/* entries from your PATH.

wallds commented 2 years ago

https://github.com/zdharma-continuum/fast-syntax-highlighting/blob/ef8ba84c3a76c768f49a0bdd2a620b2f53c2478a/CHANGELOG.md?plain=1#L99-L108

This setting should help you, although I haven't tested it yet. It looks similar to zsh-syntax-highlighting.ZSH_HIGHLIGHT_DIRS_BLACKLIST.

jcwillox commented 2 years ago

I've also been experimenting with disabling windows paths as @strawhat-dev showed and while it's a bit more work is at least a universal solution. I went down the path of using symlinks for the windows executables instead, as it's simple and then they're available globally. e.g.

sudo ln -s /mnt/c/Windows/System32/cmd.exe /usr/local/bin/cmd.exe

I've also created this little function to still allow me to easily run windows executables. It could also be made into a bash script executable.

# facilitate windows executable interop
function exe {
    target=$(wslpath "$(awk -F$'\r' 'NR == 1 {printf "%s", $1}' <<< $(/mnt/c/Windows/System32/cmd.exe /c where $1 2>/dev/null))")
    if [[ "$target" == "." ]]; then
      echo "Command '$1' not found."
    else
        $target ${@:2}
    fi
}

Now, I can run anything from the windows path, with the following.

exe powershell -nop -c echo Hello World

It's worth noting that accessing windows exe's like this you have to pay the 130ms+ cost of resolving the path, using the full path or a link to the executable is going to be faster, but this is great for one-offs.

This setting should help you, although I haven't tested it yet. It looks similar to zsh-syntax-highlighting.ZSH_HIGHLIGHT_DIRS_BLACKLIST.

Nice, that looks like what we've been looking for, I'll have to give it a try as well.