Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lag returning to prompt (especially) in git repo #447

Closed
Keilan opened this issue Mar 30, 2015 · 41 comments
Closed

Lag returning to prompt (especially) in git repo #447

Keilan opened this issue Mar 30, 2015 · 41 comments

Comments

@Keilan
Copy link

Keilan commented Mar 30, 2015

When using cmder with git (where it shows the name of my currently checked out branch next to the location), I'm finding that my commands are executed quickly but there is a major delay returning to the prompt so I can enter in another command. I notice this to some extent when I'm not in a git repo, but then the delay is almost not noticeable (100-200ms I'd guess), as opposed to 1-2 seconds in a repo.

To give further details, in my repo if I type ls, the file list comes up immediately, then the current tab changes from saying "cmd.exe" to "git.exe", and only after 1-2 seconds do I get a lambda prompt again where I can enter further commands.

I'm running Windows 8.1 and cmder.exe is installed in Program Files. Let me know if any more details would be helpful.

@Jackbennett
Copy link
Contributor

This is some problem with git, with that in mind could you just try to use some git command from a shell that isn't cmder/conemu. Just maybe commands like git status and checkout a couple of branches and status there.

If git runs that fast it must be something in cmders prompt function trying to write the status line before returning. I've found having the git status line in the prompt does have a performance hit in the tenth of a second order you describe. Any prompt function that is not just a cmder thing.

@Keilan
Copy link
Author

Keilan commented Mar 31, 2015

Hey Jack, thanks for the response. I opened Cmder and a standard windows Command Prompt and navigated to the same directory, results as follows:

Windows Cmd: ~1 second delay before git status output appears, prompt reappears immediately
Cmder: ~1 second delay before git status output appears, plus a roughly 1 second delay before prompt reappears

This is consistent with the ls output, where windows cmd is instant, and with Cmder the output is instant but there is a ~1 second delay before the prompt reappears. It seems like Cmder is running the given command as expected, but then doing something else that is causing a delay. Is there some sort of update function called when in a git repo? That would make sense given that even a non-git command such as ls results in a delay coming from git.exe.

@Jackbennett
Copy link
Contributor

When the git prompt adds to the end of that line the branch / numbers e.g [master 0 +1 0] it's just formatting its own call to git status.

From what you describe I think you've got a slow git repository. You'd best find out how you could speed it up. I could just be sheer size. I'm sure there's some tweaks to make windows faster with git.

To immediately speed that up you could remove the git parts of the prompt function cmder is calling.

@Jackbennett
Copy link
Contributor

Learning some new stuff myself here, This first answer seems like some solid advice. Check the git manual first though to see what these commands really do to your repo.

http://stackoverflow.com/questions/4485059/git-bash-is-extremely-slow-in-windows-7-x64

@Keilan
Copy link
Author

Keilan commented Mar 31, 2015

Thanks Jack, that is indeed the issue - applying the 3 settings mentioned in that SO question improved it quite a bit (I'd estimate the delay is down to 300-400ms from 1-1.5 seconds). I might look into removing the "git status" part of the prompt, as it is much more usable now, 300-400ms is still a bit much. Do you know if a setting exists for that? Or will I have to edit the source?

Anyways, marking this as closed, as the call to git status explains the issue. Thanks!

@Keilan Keilan closed this as completed Mar 31, 2015
@vladimir-kotikov
Copy link
Contributor

@Keilan you can try to replace if...end block here: https://github.com/bliker/cmder/blob/master/config/git.lua#L35 with the following line
color = colors.clean
This will decrease delays twice, but you will lose colored branch name depending on repo status.

@Jackbennett
Copy link
Contributor

I will try to add some kind of setting to flip this in the powershell side of the console for a future release. Probably not the next release though. At least git is faster now.

@ritave
Copy link

ritave commented Aug 16, 2016

I'd like to have an option to disable git showing anything on the prompt. It still slow on some occasions.

@xseneque
Copy link

I'd also like a way to disable git looking at my current repo as it gives me 30+ sec delay. It's a massive repo. I really don't care about it telling me i'm in the master branch.

How can I disable any git stuff. I just want a command prompt.

@schmich
Copy link

schmich commented Aug 31, 2016

I'm in the same boat as @xseneque. I have a large repo where git status takes around a second, so running any commands under the repo just kills all flow.

I'd really like to disable git integration. Is there any simple workaround for now, or do we have to wait for a release?

@justaniles
Copy link

After some searching, I've been able to remove git integration in the prompt, resulting in no lag when inputting commands in a git repo! The following modifications must be done to your cmder/vender/clink.lua file:

On line 41, remove {git}{hg} to prevent git/mercurial branch from being printed in your prompt:

local cmder_prompt = "\x1b[1;32;40m{cwd}\n\x1b[1;30;40m{lamb} \x1b[0m"

Comment out lines 266-267 to prevent git and mercurial plugins from running every time you press enter:

--clink.prompt.register_filter(hg_prompt_filter, 50)
--clink.prompt.register_filter(git_prompt_filter, 50)

As a note, you may want to back up this clink.lua file somewhere, in case it gets overridden after a cmder update.

Hope this helps!

@schmich
Copy link

schmich commented Sep 1, 2016

@justaniles Awesome, that's exactly what I was looking for, thanks for the help!

@jankatins
Copy link
Contributor

So what should the actual solution be here? If it should be per repo, we need to write something to the .git\ folder?

So something like this:

if not clink.get_env('CMDER_DISABLE_SCM_PROMPT') then
   -- find git dir ...
   if not git_dir_contains('cmder_disable_git_prompt') then
       -- replace {git} with the right things -> old stuff
       return
   end
end
-- replace {git} with ""

@xseneque
Copy link

xseneque commented Sep 2, 2016

Thanks @justaniles ; works like a charm!!

@valix85
Copy link

valix85 commented Mar 23, 2017

Hi guys, I have same problem... every git command spend a lot of seconds to end and return to input. I come back to windows cmd for now... I'm waiting for update.

@DaveInCaz
Copy link

DaveInCaz commented Dec 21, 2017

Is this post still the most up to date advice for this? Is there a configuration option to remove the SCM details from the prompt?

@mloskot
Copy link

mloskot commented Apr 10, 2018

In the traditional cmd with clink, there are two git look-ups run in clink.lua to refresh the prompt:

  • get_git_branch - fast, reads .git/HEAD
  • get_git_status - slow, git status which is used to decide about dirty/clean colourisation. In the whole git repo of Boost, this one takes annoyingly long time.

So, instead of disabling git information in the prompt completely, some may prefer to just get rid of the detailed/coloured status, keeping the current branch info:

λ diff -Nua c:\apps\cmder_mini\vendor\clink.lua.original c:\apps\cmder_mini\vendor\clink.lua
--- c:\apps\cmder_mini\vendor\clink.lua.original        2018-04-09 09:54:20.468732700 +0200
+++ c:\apps\cmder_mini\vendor\clink.lua 2018-04-10 08:39:57.809013700 +0200
@@ -263,11 +263,12 @@
         local color
         if branch then
             -- Has branch => therefore it is a git folder, now figure out status
-            if get_git_status() then
-                color = colors.clean
-            else
-                color = colors.dirty
-            end
+            -- XXX: Disable git status due to lag in large repo
+            -- if get_git_status() then
+                 color = colors.clean
+            -- else
+            --     color = colors.dirty
+            -- end

             clink.prompt.value = string.gsub(clink.prompt.value, "{git}", color.."("..branch..")")
             return false

Kudos to #447 (comment) for inspiration.

@DaveInCaz
Copy link

Note that this issue seems to be just as much of a problem for Mercurial as for git.

Probably the above workaround (#447 (comment)) indicates why.

@DGalt
Copy link

DGalt commented Apr 27, 2018

Are there a different set of instructions for disabling the git status in a PowerShell prompt? Find myself using PS more than cmd.exe, but the fix provided in #447 doesn't seem to work for PS.

@mloskot
Copy link

mloskot commented Apr 27, 2018

@DGalt Try this

  • edit vendor\profile.ps1
  • find this bit
[ScriptBlock]$CmderPrompt = {
    $Host.UI.RawUI.ForegroundColor = "White"
    Microsoft.PowerShell.Utility\Write-Host $pwd.ProviderPath -NoNewLine -ForegroundColor Green
    checkGit($pwd.ProviderPath)
}
  • remove checkGit($pwd.ProviderPath)
  • save and relaunch cmder

@DGalt
Copy link

DGalt commented Apr 27, 2018

@mloskot perfect, thank you!

@SidShetye
Copy link

Can the dev re-open this issue? It's still a problem and all 'fixes' here are overwritten on an update. This belongs somewhere in settings than hardcoded in a profile.ps1 script.

@loshjawrence
Copy link

loshjawrence commented Jul 30, 2018

Just discovered cmder today and downloaded to try it out. Ran into this issue in a large git repo (not all repo's do this). Every command is slow returning to the lambda prompt in the repo not just git commands. Tried all these fixes to no avail. Other terminal types (::bash ::mintty ::Powershell) don't have this issue. Very frustrating, feel like I'm being trolled by the terminal. Otherwise very useful program (love the fact there's no install and its portable).

@ghost
Copy link

ghost commented Sep 7, 2018

@mloskot Solution works for me. Great thanks man.

@victorigualada
Copy link

In the traditional cmd with clink, there are two git look-ups run in clink.lua to refresh the prompt:

  • get_git_branch - fast, reads .git/HEAD
  • get_git_status - slow, git status which is used to decide about dirty/clean colourisation. In the whole git repo of Boost, this one takes annoyingly long time.

So, instead of disabling git information in the prompt completely, some may prefer to just get rid of the detailed/coloured status, keeping the current branch info:

λ diff -Nua c:\apps\cmder_mini\vendor\clink.lua.original c:\apps\cmder_mini\vendor\clink.lua
--- c:\apps\cmder_mini\vendor\clink.lua.original        2018-04-09 09:54:20.468732700 +0200
+++ c:\apps\cmder_mini\vendor\clink.lua 2018-04-10 08:39:57.809013700 +0200
@@ -263,11 +263,12 @@
         local color
         if branch then
             -- Has branch => therefore it is a git folder, now figure out status
-            if get_git_status() then
-                color = colors.clean
-            else
-                color = colors.dirty
-            end
+            -- XXX: Disable git status due to lag in large repo
+            -- if get_git_status() then
+                 color = colors.clean
+            -- else
+            --     color = colors.dirty
+            -- end

             clink.prompt.value = string.gsub(clink.prompt.value, "{git}", color.."("..branch..")")
             return false

Kudos to #447 (comment) for inspiration.

For me, commenting the if-else block caused an error due to color property can't be found. I just removed the color.. property on the string.gsub call like this:

clink.prompt.value = string.gsub(clink.prompt.value, "{git}", "("..branch..")")

@mloskot
Copy link

mloskot commented Feb 26, 2019

Yes, that snippet above needs refinement. Here is the current version I use:

https://github.com/mloskot/wsl-config/blob/36793de0ba02de68268da554f0d548228fa57b84/win/cmder_mini/vendor/clink.lua#L365-L370

 if branch then 
     --if get_svn_status() then 
          color = colors.clean 
     --else 
     --     color = colors.dirty 
--end 

The whole idea is to avoid the heavy call to get_svn_status()

@mloskot
Copy link

mloskot commented Apr 4, 2019

The earlier tweak does not work for Cmder 1.3.11, but it should be easy to adjust the new versions of the get_git_status and get_git_conflict.

For large repos with lots of submodules, like https://github.com/boostorg/boost/, these two tweaks are sufficient for me to greatly speed the git prompt:

Simply, add --ignore-submodules to these two git commands:

cmder/vendor/clink.lua

Lines 221 to 222 in 89499f2

local function get_git_status()
local file = io.popen("git --no-optional-locks status --porcelain 2>nul")

cmder/vendor/clink.lua

Lines 236 to 237 in 89499f2

function get_git_conflict()
local file = io.popen("git diff --name-only --diff-filter=U 2>nul")

@lucas993
Copy link

lucas993 commented May 8, 2019

The earlier tweak does not work for Cmder 1.3.11, but it should be easy to adjust the new versions of the get_git_status and get_git_conflict.

For large repos with lots of submodules, like https://github.com/boostorg/boost/, these two tweaks are sufficient for me to greatly speed the git prompt:

Simply, add --ignore-submodules to these two git commands:

cmder/vendor/clink.lua

Lines 221 to 222 in 89499f2

local function get_git_status()
local file = io.popen("git --no-optional-locks status --porcelain 2>nul")

cmder/vendor/clink.lua

Lines 236 to 237 in 89499f2

function get_git_conflict()
local file = io.popen("git diff --name-only --diff-filter=U 2>nul")

Sorry guys, --ignore-submoduels didn't help for me at all.

For sure git --no-optional-locks status --porcelain 2>nul and git diff --name-only --diff-filter=U 2>nul are very slow on my system. So I think this is the correct place to find a speed up.

@TimRudy
Copy link

TimRudy commented Sep 18, 2019

Just to summarize the quick solution in 2019, this definitely solved my complaint with Cmder, that it took over 8 seconds every time I issued a command!

  • Incidentally I had Settings -> Update -> "Preferred release type" set to "Stable" which was ConEmu 180626 that came from years ago - the developer might want to note this; I changed to "Latest", so I don't short-change myself for the coming few years, but this did not make any performance difference
  • Go to C:\Program Files\Cmder\vendor, make a backup copy of clink.lua and edit it
  • In "git_prompt_filter()", delete the lines containing these:
  get_git_status()
  get_git_conflict()
  • Just leave these lines in place:
        if branch then
            color = colors.clean
            clink.prompt.value = string.gsub(clink.prompt.value, "{git}", color.."("..verbatim(branch)..")")
            return false
        end

Now commands are responsive! Instantaneous! Thank you to:
@mloskot
@justaniles Sep 1, 2016 #447 (comment)

@rohitkrishna094
Copy link

@TimRudy I can guarantee that the solution that you provided works. I tried Mr.mloskot's solution, but it didn't work for me.

I think commenting get_git_status() and get_git_conflict() is the key. Thanks.

@mloskot
Copy link

mloskot commented Sep 30, 2019

Re: @rohitkrishna094 's #447 (comment)

This is certainly not a competition but that comment may leave one quite confused.

AFAICT, the patch I presented in #447 (comment) produces this code

         if branch then
             -- Has branch => therefore it is a git folder, now figure out status
             -- XXX: Disable git status due to lag in large repo
             -- if get_git_status() then
                 color = colors.clean
             -- else
             --     color = colors.dirty
             -- end

             clink.prompt.value = string.gsub(clink.prompt.value, "{git}", color.."("..branch..")")
             return false

which, clearly, is the equivalent code to the code @TimRudy presented in #447 (comment)

        if branch then
            color = colors.clean
            clink.prompt.value = string.gsub(clink.prompt.value, "{git}", color.."("..verbatim(branch)..")")
            return false

@rohitkrishna094 I'd suggest you analyse the snippets more carefully, then you should avoid any disappointments.

@rohitkrishna094
Copy link

My bad, the diff had me confused. Would've been better if you included the output without diff in the first place. Either way thanks. And apologies. Have a nice day.

@SidShetye
Copy link

SidShetye commented Sep 30, 2019

@daxgames and @Stanzilla : Can you re-open this issue to fix the lag issue bug in cmder? Guessing most folks have switched to the new Windows Terminal app but folks still seem to be tripping over this 4 year old issue. Seems silly to block the prompt(=UI) over a long running task. Quickest solution would be to make git status opt-in by default instead of opt-out by kludgy .lua hacks. Even better, put long running tasks on a background thread.

Blocking the UI is ... so 90s.

@daxgames
Copy link
Member

@SidShetye is this related #2178.

I have never actually seen this issue.

@mloskot
Copy link

mloskot commented Oct 1, 2019

@daxgames I doubt its related. This issue is specifically about git command, not any other commands. And, this issue has been extensively investigated.

You need sufficiently large repo to suffer from it.

@develorem
Copy link

I can confirm that this will happen whenever GIT is slow, for whatever reason, not just big repositories. In my scenario, its a brand new repo with only 2 branches and 3 commits.
I have verified git itself is the issue on this Windows 10 PC. The fix defined by @TimRudy worked for me also.

Have you considered: https://github.com/romkatv/gitstatus ?
Its benchmarks for hot runs are a compelling argument.
(Note I have not used 'gitstatus' myself)

Also for anyone else new to LUA, when I made a copy of my clink.lua file, at first I didn't change the file extension, and it seems it still got picked up and executed, meaning nothing got better at first!
You need to change the extension; I just renamed my old one 'clink.lua.old' - it worked after that.

@hackhowtofaq
Copy link

hackhowtofaq commented Oct 2, 2019

@mloskot please read carefully my issue, git + all other Linux cmds ({GIT path}/usr/bin) since cmder is using these cmds if git pre-exists.

@mloskot
Copy link

mloskot commented Oct 2, 2019

@hackhowtofaq I did read it and I keep my point that #2178 has nothing to do with the slowness of git status (command prompt lag) that we are discussing in this particular issue here.

I have two different sets of Unix commands in my environment: Git's and GnuWin32.
The GnuWin32 tools, not Git's, are available in my environment when e.g. PowerShell is loaded by Cmder.

The git status is equally slow for large repos with numerous submodules (e.g. Boost C++ libraries) regardless of shell (and Unix tools) loaded by Cmder, i.e. it is slow from Git Bash, CMD or PowerShell. Disabling git status in clink.lua is the workaround to avoid lags during prompt updates.

@daxgames
Copy link
Member

daxgames commented Oct 2, 2019

@mloskot just clarifying. Disabling git status in clink somehow fixes external git in Powershell loaded in Cmder? Or any git, internal or external, in any shell loaded in cmder?

@mloskot
Copy link

mloskot commented Oct 2, 2019

@daxgames Disabling git status in clink.lua is workaround for wherever clink.lua is used. In this context here it is for Cmder.

My apologies, I wasn't clear. In my earlier comment, I just wanted to explain that I don't see any connection
between the general slowness of git status that also affects Clink/Cmder
and the slowness of Unix tools reported elsewhere.

To summarise, the problem we are discussing here is related to git command and is very simple:

  • Current implementation of git status is intrinsically slow for large and submodule-arised repos
  • Cmder's clink.lua relies on git status, hence the prompt update lags
  • Workaround: disable git status calls from clink.lua to avoid the lags

@daxgames
Copy link
Member

daxgames commented Oct 2, 2019

@mloskot Thanks, thats what I thought.. Just wanted it to be clear.

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

No branches or pull requests