【问题标题】:Jenkins git plugin - soooo slow sometimesJenkins git 插件 - 有时太慢了
【发布时间】:2014-12-31 03:11:57
【问题描述】:
以下内容来自 Jenkins 日志:
00:00:03.135 > git fetch --tags --progress git@github.com:some_org/some_repo.git +refs/heads/*:refs/remotes/origin/*
00:03:49.659 > git rev-parse origin/master^{commit} # timeout=10
我对为什么会发生这种超时感到困惑,因为在同一台机器上使用同一用户运行 git fetch 大约需要 5 到 10 秒。
我正在使用最新(撰写本文时)版本的 Git (2.1.2) 和最新版本的 gitplugin。
想法?
【问题讨论】:
标签:
git
deployment
jenkins
jenkins-plugins
【解决方案1】:
至少在我们的例子中,问题是 git 版本。
我们从 1.9 升级到 2.1.2,问题得到解决。
当我第一次发布问题时,我的错误印象是升级已经发生了..
【解决方案2】:
注意:git fetch 速度应该会在 Git 2.2+(2014 年 11 月)再次提高
请参阅 commit cbe7333,作者 Jeff King (peff):
参考:加速is_refname_available
我们的文件系统引用存储不允许 D/F(目录/文件)冲突;所以如果“refs/heads/a/b”存在,我们不允许“refs/heads/a”存在(反之亦然)。
对于文件系统强制执行条件的松散引用,这自然会失败。但
对于打包的引用,我们必须自己进行检查。
我们通过遍历整个 packed-refs 命名空间并检查每个名称是否产生冲突来做到这一点。如果你有大量的 refs,这是非常低效的,因为你最终会与 ref 树中无意义的位进行大量比较(例如,我们知道所有的“refs/tags”都是对上面的例子没有兴趣,但我们检查其中的每个条目)。
相反,让我们利用这样一个事实,即我们将打包的 refs 存储为 ref_entry 结构的 trie。
当我们遍历树时,我们可以找到提议的refname 的每个组件,同时检查 D/F 冲突。对于深度为N(即上例中为4)的refname,我们只需访问N 节点。并且在每次访问时,我们都可以在该级别对M 名称进行二分搜索,总复杂度为O(N lg M)。 (当然,每个级别的“M”是不同的,但我们可以将最坏情况的“M”作为界限)。
在将 30,000 个新 refs 提取到具有 850 万个 refs 的存储库中的病态案例中,这将运行“git fetch”的时间从几十分钟缩短到了 ~30s。
这也可能有助于我们检查松散引用(我们在重命名引用时执行)的较小情况,因为我们可以避免对不相关的松散目录进行磁盘访问。
请注意,我们添加的测试乍一看似乎与 t3210 中已有的测试是多余的。然而,早期的测试并不稳健。它们在打开 reflogs 的情况下运行,
这意味着我们实际上根本没有测试is_refname_available!
操作仍然会失败,因为 reflog 会在文件系统中遇到 D/F 冲突。
为了获得真正的测试,我们必须关闭 reflogs(但我们不想对整个脚本都这样做,因为打开它们的目的是为了覆盖一些其他情况)。