__fish_git_prompt is slow on sshfs #3083

Closed
Juerd opened this Issue May 28, 2016 · 7 comments

Projects

None yet

3 participants

@Juerd
Juerd commented May 28, 2016

When working in a git repository via sshfs, __fish_git_prompt is very slow because git rev-parse --git-dir --is-inside-git-dir --is-bare-repository --is-inside-work-tree --short HEAD takes a while to run: a few seconds on my setup.

As a workaround, I've put an alternative implementation in ~/.config/fish/functions/__fish_git_prompt.fish:

function __fish_git_prompt
    set branch_name (git symbolic-ref HEAD 2>/dev/null)
    if test -n "$branch_name"
        echo " $branch_name" | sed 's!refs/heads/!!'
    end
end

This lacks practically all of the features of the original (it only shows the current branch name), but at least I can use it via sshfs: approx. 200 ms per prompt instead of seconds. I'm sharing the workaround in case other people run into the same issue, not to suggest that this is a good fix for the underlying problem.

@faho
Member
faho commented May 28, 2016 edited

__fish_git_prompt is very slow because git rev-parse --git-dir --is-inside-git-dir --is-bare-repository --is-inside-work-tree --short HEAD takes a while to run

Have you profiled this? If not, fish --profile FILE -c '__fish_git_prompt' would give you some more information.

I'm asking because I find it quite interesting that git rev-parse --SOMESTUFF should be this slow - I'd have expected it to pretty much just check for the .git directory - which should be the cheapest possible git operation since every other git invocation needs to do as well.

Or is it the other options - the main thing we need here is --git-dir just to determine if there's anything for the prompt to do. Can you just remove the other options (and then also comment out the corresponding variables a few lines later)?

@Juerd
Juerd commented May 28, 2016

Output of sort -n FILE | tail -n 8:

10994   10994   -----> test -f $git_dir/BISECT_LOG
11601   11601   -----> test -f $git_dir/MERGE_HEAD
11926   11926   ----> test -d $git_dir/rebase-merge
12167   12167   -----> test -d $git_dir/rebase-apply
12341   12341   -----> test -f $git_dir/REVERT_HEAD
12558   12558   -----> test -f $git_dir/CHERRY_PICK_HEAD
102422  102422  -----> command git symbolic-ref HEAD ^/dev/null
1337375 1337375 --> command git rev-parse --git-dir --is-inside-git-dir --is-bare-repository --is-inside-work-tree --short HEAD ^/dev/null

Note that it's only slow when actually in a git repository via sshfs. It's fast when in a regular directory via sshfs, or in a local git repository.

When removing parts from the git rev-parse, it shows that --short is responsible for most of the delay. With strace, it shows that it stats .git/objects/pack/*.pack and then opens .git/objects/pack/*.idx. In my test case, the packed objects together are 44 accesses, 44 stats and 44 opens. Without --short, it skips that.

@faho faho added a commit that referenced this issue May 28, 2016
@faho faho Git prompt: Only shorten sha if needed
This speeds up the common case when IO is slow, e.g. when used with
sshfs.

We only use the short sha for figuring out whether the state is
valid (for which a long sha should also work) and for display when HEAD
is detached (I think that's the correct git-ism).

Working towards #3083.
aaaea44
@faho
Member
faho commented May 28, 2016

The commit I just pushed should improve the situation by only shortening the SHA when necessary - which it is in very few cases (when you've explicitly checked out a certain commit).

I'm not sure if there's anything we can do in that case - maybe just shorten to (I think) 8 characters by ourselves, since that should be long enough in all cases in existence.

@faho faho added the bug label May 28, 2016
@faho faho added this to the fish-future milestone May 28, 2016
@krader1961
Member

maybe just shorten to (I think) 8 characters by ourselves

That would be my recommendation. Even if the repo is on a local filesystem I can't see the point of paying the cost of finding the shortest unique hash. As you say eight should be more than enough in practice. Besides, it's just the prompt. It's not like we're doing anything with the value which could cause problems.

@faho
Member
faho commented May 28, 2016

I've found https://blog.cuviper.com/2013/11/10/how-short-can-git-abbreviate/, which shows that, in 2013 the linux kernel repository (which should be fairly large) needed more than 8 characters only for 0.001% of commits. Our very own repo here needs 8 characters for two commits.

So it seems 8 chars would do. Lemme whip something up.

@faho faho added a commit that closed this issue May 28, 2016
@faho faho Git prompt: Shorten the sha ourselves
Possibly fixes #3083.
8e88b29
@faho faho closed this in 8e88b29 May 28, 2016
@faho
Member
faho commented May 28, 2016

@Juerd: Please try 8e88b29. That should fix most of the delays.

@faho faho modified the milestone: next-2.x, fish-future May 28, 2016
@Juerd
Juerd commented May 29, 2016

Down to approx 400 ms; benchmarked my alternative at approx. 200 ms. In any case, while 0,4 s is still annoying, it's definitely usable now. Thank you.

A slightly related thing, though: if you hold the enter key and fill the buffer, there seems to be no way to interrupt the still somewhat slow prompt script with ^C. Should I file another issue for that?

@faho faho modified the milestone: fish 2.4.0, next-2.x Sep 4, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment