这个 git log 命令运行的时间越长,我使用的越多,如何让它运行得更快?
Posted
技术标签:
【中文标题】这个 git log 命令运行的时间越长,我使用的越多,如何让它运行得更快?【英文标题】:This git log command is takes a longer to run the more I use it, how do I make it run faster? 【发布时间】:2014-11-26 17:46:47 【问题描述】:我碰巧在使用git svn
网桥,我不确定这是否相关。在我的“.gitconfig”中,我有一个 git lg
的别名,其定义如下:
[alias]
lg = log --max-count=100 --branches --color --graph --pretty=format:'%Cred%h%Creset - %C(bold blue)<%an>%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)' --abbrev-commit
当我第一次克隆这个存储库时,运行git lg
几乎是瞬时的,但是随着时间的推移,这个命令似乎变得越来越慢。现在git lg
至少需要 30 秒。是什么导致它运行缓慢,我怎样才能让它运行得更快?
【问题讨论】:
你试过运行git gc
吗?
@ThiefMaster 嗯,实际上这有很大的不同。我不知道为什么我第一次没有注意到。我想今天我了解到git gc
加速了git log
。你觉得我应该怎么回答这个问题?
保持原样,也许有人会解释git gc
如何影响git log
...
为什么 gc 加快速度的简短答案是:它将对象收集到“包”中并删除使事情变得混乱的“死”对象。 git log
必须读取所有适用的提交对象,如果将它们从包中取出更快,那么git log
本身会更快。不过,死对象移除和对象打包的速度在很大程度上取决于操作系统和数据。此外,通常 git 会在适当的时候自动运行git gc
(当有“太多”松散的对象,无论是活的还是死的)。调整可能不适合您的系统。
【参考方案1】:
检查您是否在后台禁用了 git gc
(as in here),例如将 git config gc.auto
设置为 0 或将 git config gc.autodetach
设置为 false,或将 git config gc.pruneExpire
设置为从不。
这样您就不需要显式使用git gc
。
更一般地说,如果 git log 再次变慢,您可以使用最新版本的 Git(2.23,2019 年 8 月)调用 perf tracing:
git -c trace2.perfTarget=~/perf.log log
然后您可以看到还有什么需要时间。
7 年后更新,使用 Git 2.31(2021 年第一季度),一些漂亮的格式说明符不需要提交对象中的数据(例如“%H
”),但我们过于渴望加载和解析它,这已经变得更加懒惰了。
这有助于使某些git log --pretty
更快。
参见Jeff King (peff
)commit 018b9de(2021 年 1 月 28 日)。(由 Junio C Hamano -- gitster
-- 合并于 commit 938ecaa,2021 年 2 月 10 日)
pretty
: 扩展用户格式时延迟加载提交数据报告人:Michael Haggerty签字人:Jeff King
当我们扩展用户格式时,我们会尽量避免对输出不必要的工作。 例如,在我们知道需要作者、主题等之前,我们不会解析提交标头。
但我们总是从磁盘加载提交对象的内容,即使格式不需要它(例如,只是“
%H
”)。 传统上这并不重要,因为无论如何我们都会将它作为遍历的一部分加载,并且我们通常会将这些字节附加到提交结构(或者这些天,缓存在提交板中)。但是当我们有一个提交图时,我们可能很容易到达漂亮打印提交的地步,而无需查看实际的对象内容。 我们应该推迟这个负载(和重新编码),直到我们确定它是需要的。
我认为 p4205 的结果非常清楚地显示了优势(我们从提交结构本身提供父和树 oid,因此它们也受益):
# using git.git as the test repo Test HEAD^ HEAD ---------------------------------------------------------------------- 4205.1: log with %H 0.40(0.39+0.01) 0.03(0.02+0.01) -92.5% 4205.2: log with %h 0.45(0.44+0.01) 0.09(0.09+0.00) -80.0% 4205.3: log with %T 0.40(0.39+0.00) 0.04(0.04+0.00) -90.0% 4205.4: log with %t 0.46(0.46+0.00) 0.09(0.08+0.01) -80.4% 4205.5: log with %P 0.39(0.39+0.00) 0.03(0.03+0.00) -92.3% 4205.6: log with %p 0.46(0.46+0.00) 0.10(0.09+0.00) -78.3% 4205.7: log with %h-%h-%h 0.52(0.51+0.01) 0.15(0.14+0.00) -71.2% 4205.8: log with %an-%ae-%s 0.42(0.41+0.00) 0.42(0.41+0.01) +0.0% # using linux.git as the test repo Test HEAD^ HEAD ---------------------------------------------------------------------- 4205.1: log with %H 7.12(6.97+0.14) 0.76(0.65+0.11) -89.3% 4205.2: log with %h 7.35(7.19+0.16) 1.30(1.19+0.11) -82.3% 4205.3: log with %T 7.58(7.42+0.15) 1.02(0.94+0.08) -86.5% 4205.4: log with %t 8.05(7.89+0.15) 1.55(1.41+0.13) -80.7% 4205.5: log with %P 7.12(7.01+0.10) 0.76(0.69+0.07) -89.3% 4205.6: log with %p 7.38(7.27+0.10) 1.32(1.20+0.12) -82.1% 4205.7: log with %h-%h-%h 7.81(7.67+0.13) 1.79(1.67+0.12) -77.1% 4205.8: log with %an-%ae-%s 7.90(7.74+0.15) 7.81(7.66+0.15) -1.1%
我添加了最后的测试来显示我们没有改进的地方(那 1% 只是幸运的噪音),但也作为回归测试来确保我们没有做任何愚蠢的事情,比如多次加载提交时有几个占位符需要它。
另一种方法是使用 %d,如“How do I show tags in a custom git log format?”中所述。
使用 Git 2.33(2021 年第三季度)会更快,它优化了“git log
”(man),以应对我们浪费周期来加载可能不需要的参考装饰数据的情况。
请参阅commit d1ed8d6(2021 年 7 月 14 日)和 commit 6afb265、commit 88473c8、commit 7463064、commit 542d6ab、commit b2086b5、commit b2086b5、commit 3c7e2e8(2021 年 6 月 22 日)Jeff King (peff
)。(2021 年 7 月 28 日在 commit c9d6d8a 中由 Junio C Hamano -- gitster
-- 合并)
load_ref_decorations()
: 避免解析非标签对象签字人:杰夫·金
当我们加载 ref 装饰时,我们会解析每个 ref 指向的对象,以获得一个“结构对象”。 这是不必要的昂贵;我们真的只需要对象结构,甚至不看解析的内容。 例外是标签,我们确实需要剥离。
我们可以通过首先查找对象类型来改进这一点(这样更便宜),然后完全跳过对非标签的解析。 这略微增加了带注释标签的工作量(现在进行类型查找 和 解析),但对于其他类型则减少了很多。
总的来说,这似乎是一个很好的权衡。
在我的 git.git 克隆中,大约 2k 引用,其中大部分是分支,运行“git log -1 --decorate
”(man) 的时间从 34 毫秒下降到 11 毫秒。李> 即使在我的 linux.git clone
(man) 上,它主要包含标签和少数分支,时间也从 30 毫秒下降到 19 毫秒。 在更极端的实际案例中,大约 220k 引用(主要是非标签),时间从 2.6 秒下降到 650 毫秒。当然,该命令是一个不平衡的示例,因为它尽可能少地执行非加载工作。 但它确实显示了绝对的时间改进。 即使在那个极端的 repo 上像一个完整的 "
git log --decorate
"(man),我们仍然可以节省 2 秒的 CPU 时间。
【讨论】:
以上是关于这个 git log 命令运行的时间越长,我使用的越多,如何让它运行得更快?的主要内容,如果未能解决你的问题,请参考以下文章