Cygwin/MinGW中Git difftool的速度非常慢

now*_*wox 7 git benchmarking cygwin mingw git-difftool

我注意到这git difftool很慢.每次diff调用之间会出现大约1..2秒的延迟.

要对它进行基准测试,我编写了一个自定义difftool

#!/bin/sh
echo $0 $1 $2
Run Code Online (Sandbox Code Playgroud)

并配置Git在我的使用中使用此工具 ~/.gitconfig

[diff]
    tool = mydiff
[difftool "mydiff"]
    prompt = false
    cmd = "~/mydiff \"$LOCAL\" \"$REMOTE\""
Run Code Online (Sandbox Code Playgroud)

我在Git源代码上测试了它:

$ git clone https://github.com/git/git.git
$ cd git
$ git rev-parse HEAD
1bc8feaa7cc752fe3b902ccf83ae9332e40921db
$ git diff head~10 --stat --name-only | wc -l
23
Run Code Online (Sandbox Code Playgroud)

当我计时git difftool259b5e6d33,结果非常缓慢:

$ time git difftool 259b5
mydiff /dev/null Documentation/RelNotes/2.6.3.txt
...
mydiff /tmp/mY2T6l_upload-pack.c upload-pack.c

real    0m10.381s
user    0m1.997s
sys     0m6.667s
Run Code Online (Sandbox Code Playgroud)

通过尝试更简单的脚本,它会更快:

$ time git diff --name-only --stat 259b5 | xargs -n1 -I{} sh -c 'git show 259b5:{} > {}.tmp && ~/mydiff {} {}.tmp'
mydiff Documentation/RelNotes/2.6.3.txt Documentation/RelNotes/2.6.3.txt.tmp
mydiff upload-pack.c upload-pack.c.tmp

real    0m1.149s
user    0m0.472s
sys     0m0.821s
Run Code Online (Sandbox Code Playgroud)

我错过了什么?

这是我得到的结果

| Cygwin | Debian | Ubuntu | Method   |
| ------ | ------ | ------ | -------- |
| 10.381 |  2.620 | 0.580  | difftool |
|  1.149 |  0.567 | 0.210  | custom   |
Run Code Online (Sandbox Code Playgroud)

对于Cygwin结果,我测量了花费的2.8s git-difftool和花费的7.5s git-difftool--helper.后者长98线.我不明白为什么这么慢.

Gal*_*boy 2

使用msysgit GitHub 上找到的一些技术,我已经缩小了范围。

对于 diff 中的每个文件git-difftool--helper重新运行以下内部命令:

12:44:46.941239 git.c:351               trace: built-in: git 'config' 'diff.tool'
12:44:47.359239 git.c:351               trace: built-in: git 'config' 'difftool.bc.cmd'
12:44:47.933239 git.c:351               trace: built-in: git 'config' '--bool' 'mergetool.prompt'
12:44:48.797239 git.c:351               trace: built-in: git 'config' '--bool' 'difftool.prompt'
12:44:49.696239 git.c:351               trace: built-in: git 'config' 'difftool.bc.cmd'
12:44:50.135239 git.c:351               trace: built-in: git 'config' 'difftool.bc.path'
12:44:50.422239 git.c:351               trace: built-in: git 'config' 'mergetool.bc.path'
12:44:51.060239 git.c:351               trace: built-in: git 'config' 'difftool.bc.cmd'
12:44:51.452239 git.c:351               trace: built-in: git 'config' 'difftool.bc.cmd'
Run Code Online (Sandbox Code Playgroud)

请注意,在本例中,执行这些命令大约需要 4.5 秒。这是我的日志中非常一致的模式。

另请注意,其中一些是重复的 -git config difftool.bc.cmd被调用 4 次!

现在,可能的补救措施:

  • 通过将所有与差异相关的部分移至文件顶部,我将这些命令的执行时间减少了一半.gitconfig。严重地。它仍然很明显,但现在约为 2 秒,而不是 4.5 秒。
  • 确保 Program Files 下的 Git 文件夹和您的用户配置文件(所在.gitconfig位置)均被排除在实时病毒扫描之外。
  • 从根本上来说,Git 需要更高效地解析和获取配置值。理想情况下,它会缓存这些而不是每次循环时都从配置中重新请求(并重新解析...)。甚至可能缓存整个命令执行。