7

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

为了对其进行基准测试,我编写了一个自定义difftool命令:

#!/bin/sh
echo $0 $1 $2

并将 Git 配置为在我的~/.gitconfig

[diff]
    tool = mydiff
[difftool "mydiff"]
    prompt = false
    cmd = "~/mydiff \"$LOCAL\" \"$REMOTE\""

我在 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

当我用 a 计时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

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

$ 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

我错过了什么?

这是我得到的结果

| Cygwin | Debian | Ubuntu | Method   |
| ------ | ------ | ------ | -------- |
| 10.381 |  2.620 | 0.580  | difftool |
|  1.149 |  0.567 | 0.210  | custom   |

对于Cygwin结果,我测量了 2.8 秒git-difftool和 7.5 秒的git-difftool--helper. 后者有 98 行长。我不明白为什么这么慢。

4

3 回答 3

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'

请注意,在这种特殊情况下,执行这些操作大约需要 4.5 秒。这是我整个日志中非常一致的模式。

还要注意,其中一些是重复的——git config difftool.bc.cmd被调用了 4 次!

现在,可能的补救措施:

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

git difftool使用 Git 2.13(2017 年第二季度)应该会稍微快一些,
请参阅Jeff Hostetler ( ) 的commit d12a8cf(2017 年 4 月 14 日(由Junio C Hamano 合并 -- --8868ba1 提交中,2017 年 4 月 24 日)jeffhostetler
gitster

unpack-trees: 避免在结帐期间重复 ODB 查找

(ODB:对象数据库)

当两个目录引用相同的 OID 时,教导traverse_trees_recursive()不要进行冗余 ODB 查找。

在 和 等操作中read-treecheckout当提交之间的差异相对较小时,可能会有许多具有相同 OID 的对等目录。
在这些情况下,我们可以避免多次针对同一个 OID 访问 ODB。

此补丁处理 n=2 和 n=3 的情况,并简单地复制数据而不是重复 fill_tree_descriptor()。

================

在 Windows 存储库(500K 树,3.1M 文件,450MB 索引)上,这将在 2 次提交之间循环且具有单个文件差异的总时间减少了 0.75 秒。

(avg) before: 22.699
(avg) after:  21.955
===============
于 2017-04-26T22:14:28.827 回答
1

经过一番调查,我有证据表明性能不佳与来自不同域的用户拥有的文件有关。具体来说,我得出以下结论:

  • 我在一个拥有多个域和数千名用户的公司环境中工作。
  • 由于组织变化,每个用户可能仅在过渡阶段被保存在两个域中,即他或她的主域以及第二个域。通过 Windows GUI 更改对象所有权时,每个用户会出现两次,并且必须转到扩展用户选择以识别分配给特定域的用户。
  • 启用acl的cygwin将“其他域”文件用户显示为“<域>+<用户名>”。主域自身就是“<username>”。没有 acl的Cygwin在这两种情况下都只显示“<用户名>”。这可能会相当令人困惑,因为 cygwin 识别的文件权限和所有权将指示写权限,而用户实际上没有。
  • 属于“其他域”自身的文件可由我的“本域”自身写入,因此域分配在很大程度上是透明的。
  • 我们的版本控制系统中的一个大型源代码树(也反映在 git 存储库中)有数千个文件由“其他域自身”拥有。这似乎导致文件操作缓慢。将所有权更改为“主域自身”解决了 git 和其他文件访问的速度问题。

我必须假设为其他域中的用户获取文件权限很慢,并且由于某种原因没有缓存(它始终是同一个用户)。

以下文章的其余部分是我最初发布的内容。我让它站着。


对我来说(在一家拥有多个地理分布的 Windows 域的大公司工作),罪魁祸首是 cygwin默认使用Windows acl 。考虑对域中所有已知用户的此请求:

$ time (mkpasswd -D | wc -l)
45183

real    27m55,340s
user    0m1,637s
sys     0m0,123s

修复 (1)(2) 是一个简单的问题,即使用 挂载 NTFS 文件系统noacl,即 my/etc/fstab包含该行

none / cygdrive binary,posix=0,user,noacl 0 0

(同时消除烦人的cygdrive前缀)。

我不禁想象 cygwin/msys(那里的行为相同,除了 Windows git 安装noacl默认安装,可能是因为这个原因)对它接触的每个文件执行域服务器查询并且不缓存结果。

该更改是在 2015 年左右的某个时间与 cygwin 2.4 或 2.5 一起引入的。从2.4 的发行说明:

为了适应标准 Windows ACL,所有者和 ACL 中所有其他用户的 POSIX 权限是使用 Windows AuthZ API 计算的。在某些情况下,这可能会显着减慢 POSIX 权限的计算[...](我强调)。

noacl选项将启动 BeyondCompare(或回显字符串)的时间从 25 秒减少到 1 秒。完全无法理解为什么git diff即使使用 acl 对同一文件执行简单操作也非常快,因为我天真地假设所需的信息因此所需的 FS 操作是相同的。

我会检查一下cygserver现在可以通过缓存来改进的东西。

更新:不幸的是,cygserver 并没有改善这种情况。


(1) git 的修复。mkpasswd不受影响。

(2) 我还没有理解和测试对 git 的文件权限和所有权的影响(以及我们也通过 cygwin 访问的 ClearCase 视图)。我的直觉是,人们希望尽可能地忠于 Windows 语义(这意味着noacl可能会遇到问题)。

(3) cygwin 文档讨论了查询结果没有被缓存的场景。一个由一系列 cygwin 进程组成,这些进程不是从共同的 cygwin 祖先(如 bash)产生,而是从 Windows 程序如cmd. 我必须假设 Windows 为本地程序提供了缓存机制,否则 Windows 系统将无法在这种企业环境中使用。由于某种原因 cygwin 不使用它。

于 2017-05-18T14:53:43.127 回答