与 Libgit2 相比,Windows 上的 Git 存储速度极慢

Posted

技术标签:

【中文标题】与 Libgit2 相比,Windows 上的 Git 存储速度极慢【英文标题】:Git stash on windows extremly slow compared to Libgit2 【发布时间】:2017-10-24 21:14:03 【问题描述】:

最近我已经多次使用 git stash 并且我一直认为它真的很慢,即使在具有单个文件的新存储库上也是如此。我已阅读 this question 关于 git stash 缓慢和 this other one 并尝试了这些问题的所有答案,但实际上没有任何效果。

例如,我已完成以下步骤来重现它:

    git init touch file.txt vim file.txt(编辑文件添加2行) git add . git commit -m "Initial commit" vim file.txt(再次编辑添加 1 行) time git stash

输出:

$ time git stash
Saved working directory and index state WIP on master: b9454ed Initial commit
HEAD is now at b9454ed Initial commit    
real    0m8.042s
user    0m0.000s
sys     0m0.046s

8 秒存储单行是这么多时间。 现在使用 libgit2sharp 进行测试:

static void Main(string[] args)

    Repository repo=new Repository(@"C:\Users\UserTest\TestGitRepo");

    repo.Stashes.Add(new Signature("test", "test@test.com", new DateTimeOffset(DateTime.Now)), "Stash on master");

此代码需要 74 毫秒来存储相同的更改。 如果 Libgit2 这么快,那么应该可以加快 git stash 命令的速度。我怎样才能做到这一点?

实际使用的是 windows 10 64bit 和 git 2.11 64bits。其他 git 命令(如状态、添加、提交等)工作正常。

更新:我已经更新到 git 2.13,现在 git stash 是 14,53s...

更新 2:我已更新到 git 2.15 并尝试相同的测试 time git stash 返回 real 0m6,553s。还是很慢……

【问题讨论】:

实际上,在我的电脑上创建了一个sh.exe.stackdump,你能验证git stash确实做了它应该做的事情吗? @LasseV.Karlsen 它达到了预期的效果。最后一行在两种情况下都使用我的问题的步骤隐藏。 是的,这条线也藏在我这边,但 bash 也因堆栈溢出而崩溃。但这并没有考虑到所花费的时间,所以请忽略我的 cmets。 啊,由于某种原因,我设法回到 64 位版本的 git,它在 bash 中存在堆栈溢出异常问题。恢复了 32 位,故障转储消失了。 许多 Git 命令被编写为 shell 脚本。在 Linux 和 Unix 系统上,它们在完全合理的时间内运行。在 Windows 上,显然(我不使用 Windows,所以我没有经历过这种情况),它们运行得非常缓慢。因此,Git 人员一直在重写越来越多的 Git 命令,以避免使用 shell 脚本。我想知道修复导致 shell 如此缓慢的任何问题是否更有利可图,但这也许是 Windows 的基础。 【参考方案1】:

自 Git 2.22

从 Git 2.22 开始,之前的实验性功能现已稳定并成为默认选项。

低于 Git 2.22

一年后,安装 Git 2.19 我在 git 安装期间看到了一个复选框,用于启用新的 experimental 内置存储。

在我的情况下,它运行良好,并且我注意到与旧实现(使用脚本)相比巨大的性能改进,它实际上与在 linux 中使用相同的命令一样快。

这里的结果完全相同的步骤:

$ time git stash
Saved working directory and index state WIP on master: 7a29b92 Initial commit

real    0m0,120s
user    0m0,000s
sys     0m0,015s

【讨论】:

【参考方案2】:

要添加到现有答案,如果您已经安装了 2.19 或更高版本,则可以启用新功能:

git config --global stash.usebuiltin true

这也适用于便携版。

请注意,此功能似乎还不适用于子模块。 https://github.com/git-for-windows/git/issues/1820

【讨论】:

看起来他们在你回答后不久就关闭了那个错误!【参考方案3】:

git stash 使用 Git 2.25(2020 年第一季度)将更快,oneway_merge() 的用户(如“reset --hard”)学会了利用fsmonitor 来避免不必要的lstat(2) 调用。

(从 Git 2.22 开始,2019 年第二季度,git stash is entirely rewritten in C,并且是默认值)

参见Utsav Shah (Utsav2) 的commit 679f2f9(2019 年 11 月 20 日)。(由 Junio C Hamano -- gitster -- 合并于 commit 473b431,2019 年 12 月 5 日)

unpack-trees: 跳过 fsmonitor 有效文件的统计信息

协助人:Junio C Hamano协助人:Kevin Willford签字人:Utsav Shah

索引可能知道一个文件没有通过fsmonitor 修改,但 unpack-trees 没有注意到它并通过ie_match_stat 进行检查,这在某些文件系统上可能效率低下。 这会显着减慢运行oneway_merge 的命令,例如checkoutgit reset --hard

这个补丁让oneway_merge通过fsmonitor检查一个文件是否被认为没有改变,并跳过ie_match_stat。 unpack-trees 现在也可以正确地从源索引中复制 fsmonitor 有效性状态。 最后,为了正确起见,我们强制刷新tweak_fsmonitor 中的fsmonitor 状态。

在此更改之后,像 stash 之类的命令(在内部使用 git reset --hard在 mac 上的 250k 文件存储库上从 8 秒或更多到 ~2 秒 .

【讨论】:

以上是关于与 Libgit2 相比,Windows 上的 Git 存储速度极慢的主要内容,如果未能解决你的问题,请参考以下文章

VisualStudio:libgit2 引发错误。类别 = 结帐

c++ Windows 调试性能与 linux 相比非常慢

在 Clion 中链接 libgit2 不起作用

如何使用 libgit2sharp 正确取消暂存文件

是否可以在 Windows 中将 nvcc 与 gcc/g++ 集成?

libgit2-6311e88: cannot open shared object file: No such file or directory