我正在尝试git blame以下文件(在我的本地机器上运行),因为它太慢了,无法生成GitHub的错误:
https://github.com/Homebrew/homebrew-core/blob/master/Formula/sqlite.rb
但是在本地运行它也非常慢,在我的机器上运行超过一分钟
存储库包含超过15万个提交。
有没有一种方法可以加快git blame命令的执行速度?
发布于 2019-09-08 10:32:15
根据Git标准,自制核心存储库相当大。一个250MB的存储库,对于4000个“公式”,提交了150,000个。这可能会影响性能。Github确实遇到了麻烦。
在我的2018年i7 Macbook上使用Git2.22.0时,git blame Formula/sqlite.rb大约需要45秒。虽然以Git标准来说速度很慢,但考虑到运行git blame的频率,这是可以接受的。
作为这个存储库的用户,没什么可做的。git blame必须向后搜索每个提交,以查看哪些提交更改了此文件。不幸的是,git blame似乎没有利用并行处理的优势。
有一些选择..。
就这个问题联系Github,希望他们能解决这个问题。
限制你回顾历史的时间:git blame --since=1.year in Formula/sqlite.rb
重新考虑在此存储库上需要快速git blame的任何进程。
缓存结果。
发布于 2020-05-03 03:57:56
在Git2.27 (Q2 2020)中,"git blame“学会利用存储在提交图文件中的"changed-paths”布隆过滤器,并在git log中引入。
参见Jeff King (peff)的commit 1b4c57f,commit 24b7d1e,commit fe88f9f (2020年4月23日)。
见Derrick Stolee (derrickstolee)的commit 0906ac2,commit b23ea97,commit 8918e37 (2020年4月16日)。
(由Junio C Hamano -- gitster合并,提交6d56d4c,2020年5月1日)
blame:使用changed-path布隆过滤器
签名者: Derrick Stolee
changed-path布隆过滤器有助于减少历史查询过程中所需的树解析次数。
在计算diff之前,我们可以询问过滤器是否在提交和它的第一个父级之间更改了路径。
如果筛选器说“不”,那么我们可以在不解析树的情况下继续进行操作。
如果过滤器说“可能”,那么我们解析树来发现答案实际上是“是”还是“否”。
在计算指责时,find_origin()中有一个部分计算提交和它的一个父级之间的差异。
当这是第一个父级时,我们可以在调用diff_tree_oid()之前检查布隆过滤器。
为了使这与指责机制一起工作,我们需要用初始路径初始化一个结构bloom_key。但是,如果检测到重命名,我们还需要向列表中添加更多的键。然后,我们检查这些键中是否有任何键在diff中回答“可能”。
如果用户使用"git blame -C“请求复制检测,那么有更多地方可以扩展”重要“文件集。我对这是如何在指责机制中发生的了解还不够。
因此,Bloom filter集成在此模式下被显式禁用。
稍后的更改可以通过对add_bloom_key()的适当调用(或多个调用)来扩展bloom_key数据。
一般来说,这是一个性能增强,不应该以任何方式改变'git blame‘的行为。
如果存储库有一个带有计算的更改路径布隆过滤器的提交图文件,那么他们应该注意到他们的'git blame‘命令的性能提高了。
以下是我通过指责Linux内核存储库中的一些路径发现的一些示例计时:
git blame arch/x86/kernel/topology.c >/dev/null`
前: 0.83s后: 0.24s
git blame kernel/time/time.c >/dev/null
前: 0.72s后: 0.24s
git blame tools/perf/ui/stdio/hist.c >/dev/null
前: 0.27s后: 0.11s
我特别寻找了“深度”路径,这些路径也被编辑了很多次。
与此相对的是,MAINTAINERS文件被编辑了多次,但它位于根树中。
这意味着相对于路径规范计算diff的成本非常小。下面是该命令的时间:
git blame MAINTAINERS >/dev/null
之前: 20.1s之后: 18.0s
这些计时是五个计时中最好的。
对于这两种情况,最坏的运行时间都在2.5分钟左右。
注意,在17,000+提交中,MAINTAINERS文件有18,740行。这恰好是这种更改提供的改进最少的情况之一。
MAINTAINERS文件没有改进,而其他示例的改进相对较小,这很容易解释。
指责机制需要计算行级差异,以确定每次提交更改了哪些行。这占了计算时间的很大一部分,而且这种更改并不会试图改进算法的这一部分。
MAINTAINERS文件很大,而且经常更改,因此需要花费一些时间来确定哪些行是由哪个commit更新的。相比之下,代码文件要小得多,计算Linux邮件列表中单个补丁的逐行差异所需的时间也更长。
除了"-C“集成之外,我相信在此补丁之后,从”git blame“的更改路径布隆过滤器中获得的好处不多。
不过,请确保使用Git2.29 (Q4 2020),因为有一个小错误:
见Edmundo Carmona Antoranz (eantoranz)提交的1302ad(2020年9月8日)。
(由Junio C Hamano -- gitster合并-在commit e1dd499,2020年9月18日)
blame.c:替换oideq的!oidcmp实例
署名者: Edmundo Carmona Antoranz
0906ac2b ("blame:use changed-path Bloom filters",2020-04-16,Git v2.27.0-rc0 -- oideq()在批次#6中列出)引入了对oidcmp()的调用,该调用在14438c44中引入(“引入hasheq()和oideq()",2018-08-28,Git v2.20.0-rc0 --合并在批次#1中列出)。
在Git2.29 (Q4 2020)中,"git commit-graph(man) write“学会了使用--max-new-filters选项限制从头开始计算的布隆过滤器的数量。
这将使git blame受益。
参见提交d356d5d,提交98bb796,提交59f0d50,提交97ffa4f (2020年9月17日),提交809e032 (2020年9月18日),提交9a7a9ed,提交312cff5 (2020年9月16日),以及Taylor Blau (ttaylorr)的commit b66d847,commit 24f951a,commit ab14d06,commit 025d529,commit 4f36440 (2020年9月9日)。
参见Derrick Stolee (derrickstolee)的commit b16a827 (2020年9月16日)。
(由Junio C Hamano -- gitster合并,提交288ed98,2020年9月29日)
builtin/commit-graph.c:引入‘--max-new-filter=’
帮助: Junio C Hamano
签名者:泰勒·布劳
引入命令行标志来指定“git commit-graph write”(Man)愿意从头开始计算的新布隆过滤器的最大数量。
在此补丁之前,使用'--changed-paths‘的提交图写入将为所有尚未计算的选定提交计算布隆过滤器(即,通过使用'--split’的前一次提交图写入,以便执行上卷或替换)。
由于各种原因,此行为可能会导致长得令人望而却步的提交图写入:
可能有很多过滤器的差异需要很长时间才能生成(例如,它们的变化次数接近最大值,差异本身需要很长时间,等等)。
老式的提交图(对带有太多条目的过滤器进行编码,因为根本没有计算过)导致我们浪费时间重新计算似乎没有计算过的过滤器,结果发现它们太大了。
这可能会使'git commit-graph write --changed-paths'(man)所需时间的上限变得相当不可预测。
要使此命令的行为更具可预测性,请引入“--max-new-filters=”,以允许从头开始计算至多“”布隆过滤器“。
这让“计算”已知的过滤器快速进行,同时限制了Git愿意完成的缓慢任务的数量。
git commit-graph现在的手册页中包括
使用--max-new-filters=选项,最多生成n新的布隆过滤器(如果指定了--changed-paths )。
如果n为-1,则不强制执行任何限制。
只有出现在新层中的提交数才会计入此限制。
要追溯计算早期层上的布隆过滤器,建议使用--split=replace。
使用Git2.31 (Q1 2021),在"git blame"(man)中进行优化
见Rafael Silva (raffs)提交的8e16efff(2021年2月17日)。
(由Junio C Hamano -- gitster合并,提交18decfd,2021年2月25日)
blame:删除不必要的get_commit_info()使用
签发人:拉斐尔·席尔瓦
审阅者: Taylor Blau
当git blame(man)为--color-by-age时,将调用determine_line_heat()来选择如何根据提交的作者日期对输出进行着色。
它使用get_commit_info()将信息解析为commit_info结构,但是,这实际上是不必要的,因为determine_line_heat()调用者也执行同样的操作。
相反,让我们将determine_line_heat()更改为采用commit_info结构,并删除对get_commit_info()的内部调用,从而清理和优化代码路径。
开启Git的trace2接口,记录每次调用determine_line_heat()函数的执行时间:
trace2_region_enter("blame","determine_line_heat",the_repository);determine_line_heat(ent,&default_color);+ trace2_region_enter("blame","determine_line_heat",the_repository);
然后,在linux.git中为"kernel/fork.c“运行git blame,并对每个调用(大约1.3k个调用)的所有执行时间进行求和,结果是执行速度提高了2.6倍(最佳输出3):
从328c109303 (第八批,2021-02-12)构建的git =从328c109303构建的git = 42ms +此更改= 16ms
https://stackoverflow.com/questions/57837986
复制相似问题