当前位置:  开发笔记 > 编程语言 > 正文

对于100,000个对象,Git非常慢.任何修复?

如何解决《对于100,000个对象,Git非常慢.任何修复?》经验,为你挑选了4个好方法。

我有一个"新鲜的"git-svn repo(11.13 GB),其中有超过100,000个对象.

我已经做好了

git fsck
git gc

在初步结账后的回购.

然后我试着去做

git status

执行git状态所需的时间是2m25.578s和2m53.901s

我通过发出命令测试了git status

time git status

5次,所有时间都在上面列出的两次之间.

我在Mac OS X上执行此操作,本地而非通过VM.

它不应该花这么长时间.

有任何想法吗?救命?

谢谢.

编辑

我有一个同事坐在我旁边,有一个类似的盒子.减少RAM并使用jfs文件系统运行Debian.他的git状态在同一个回购中运行.3(它也是一个git-svn checkout).

另外,我最近在这个文件夹上更改了我的文件权限(到777),它大大缩短了时间(为什么,我没有线索).我现在可以在3到6秒之间完成任务.这是可以控制的,但仍然很痛苦.



1> manumoomoo..:

它归结为我现在能看到的几件物品.

    git gc --aggressive

    打开文件权限 777

必须有其他事情发生,但这显然是影响最大的事情.


来自Linus的一些见解:http://metalinguist.wordpress.com/2007/12/06/the-woes-of-git-gc-aggressive-and-how-git-deltas-work/
-1,抱歉.`git gc --aggressive`可能已经解决了你的具体问题,但它会弄乱好包.一个gc +一个积极的重新包装可能会更好(参见上面的@ Charles链接),然后重新克隆(`git clone file:///Users/foo/bar/myrepo/.git newclone`).

2> masonk..:

git status必须每次查看存储库中的每个文件.您可以告诉它停止查看您没有使用的树木

git update-index --assume-unchanged 

资源

从联机帮助页:

指定这些标志时,不会更新为路径记录的对象名称.相反,这些选项设置和取消设置路径的"假定未更改"位.当"假定未更改"位打开时,git停止检查工作树文件是否有可能的修改,因此您需要手动取消设置该位以在更改工作树文件时告诉git.当在具有非常慢的lstat(2)系统调用(例如cifs)的文件系统上处理大项目时,这有时是有用的.

此选项还可以用作粗略的文件级机制,以忽略跟踪文件中未提交的更改(类似于.gitignore对未跟踪文件的更改).如果需要在索引中修改此文件,例如在提交中合并时,Git将失败(优雅); 因此,如果上游更改了假定未跟踪文件,则需要手动处理该情况.

git中的许多操作依赖于您的文件系统以实现高效的lstat(2)实现,因此可以便宜地检查工作树文件的st_mtime信息,以查看文件内容是否已从索引文件中记录的版本更改.不幸的是,一些文件系统的效率低下lstat(2).如果您的文件系统是其中之一,则可以将"假设未更改"位设置为未更改的路径,以使git不执行此检查.请注意,在路径上设置此位并不意味着git将检查文件的内容以查看它是否已更改 - 它使git省略任何检查并假设它未更改.当您对工作树文件进行更改时,必须通过在修改它们之前或之后删除"假定未更改"位来明确告诉git.

...

要设置"假定未更改"位,请使用--assume-unchanged选项.要取消设置,请使用--no-assume-unchanged.

该命令查看core.ignorestat配置变量.如果这是真的,使用git update-index路径更新路径...并使用更新索引和工作树的其他git命令更新路径(例如git apply --index,git checkout-index -u和git read-tree -u )自动标记为"假设不变".注意,如果git update-index --refresh发现工作树文件与索引匹配,则不设置"假定未更改"位(如果要将它们标记为"假定未更改",请使用git update-index --really-refresh).


现在,很明显,如果您可以方便地忽略回购的某些部分,此解决方案才会起作用.我在一个类似规模的项目上工作,肯定有大树,我不需要定期检查.git-status的语义使其成为一般的O(n)问题(文件数量为n).您需要特定于域的优化才能做得更好.

请注意,如果您使用拼接模式,即如果您通过合并而不是rebase从上游集成更改,则此解决方案变得不太方便,因为从上游合并的--assume-unchanged对象的更改将变为合并冲突.您可以使用基础工作流程来避免此问题.



3> VonC..:

git status 应该在Git 2.13(2017年第二季度)中更快,因为:

关于字符串优化数组的优化(参见" 提高git status性能的方法 ")

更好的"读缓存"管理.

关于最后一点,请参阅Jeff Hostetler()提交a33fc72(2017年4月14日).(由Junio C Hamano合并- -提交cdfe138,2017年4月24日)jeffhostetler
gitster

read-cache: force_verify_index_checksum

教导git跳过在verify_hdr()调用索引文件末尾的SHA1-1校验和的验证,read_index()除非设置了" force_verify_index_checksum"全局变量.

教会fsck强制进行此验证.

校验和验证用于检测磁盘损坏,对于小型项目,计算SHA-1所需的时间并不重要,但对于巨大的存储库,此计算会为每个命令增加大量时间.


Git 2.14通过更好地考虑" 未跟踪的缓存 "来改善git状态性能,这允许Git stat使用结构的mtime字段跳过读取未跟踪的目录(如果他们的数据没有改变)stat.

有关Documentation/technical/index-format.txt未跟踪缓存的更多信息,请参阅.

请参阅David Turner()提交的edf3b90(2017年5月8日).(由Junio C Hamano合并- -fa0624f,2017年5月30日)dturner-tw
gitster

当" git checkout"," git merge"等操纵核心内索引时,索引扩展中的各种信息将从原始状态中丢弃,因为通常情况下它们不会保持最新并且在 -与主索引上的操作同步.

现在,在这些操作中复制未跟踪的缓存扩展,这将加速"git status"(只要缓存被正确无效).


更一般地说,使用Git 2.14.x/2.15写入缓存也会更快

请参阅提交ce012de,提交b50386c,提交3921a0b(2017年8月21日)作者:Kevin Willford(``).
(由Junio C gitsterHamano合并- -在提交030faf2,2017年8月27日)

在编写每个索引条目时,我们过去花费的时间超过必要的周期来分配和释放内存.
这已经过优化.

当索引超过一百万个条目且小回购没有性能下降时,[那]将节省3-7%.


2017年12月更新:Git 2.16(2018年第一季度)将提出一个额外的增强功能,这一次git log,因为迭代松散的目标文件的代码刚刚得到优化.

见Derrick Stolee()提交163ee5e(2017年12月4日).(由Junio C Hamano合并- -97e1f85承诺中,2017年12月13日)derrickstolee
gitster

sha1_file:用strbuf_add()而不是strbuf_addf()

在枚举松散对象时替换使用strbuf_addf()with .由于我们在使用路径之前已经检查了字符串的长度和十六进制值,因此我们可以通过使用较低级别的方法来防止额外的计算.strbuf_add()for_each_file_in_obj_subdir()

一个消费者for_each_file_in_obj_subdir()是缩写代码.OID(对象标识符)缩写使用缓存对象的缓存列表(每个对象子目录)来快速重复查询,但是当存在许多松散对象时,存在显着的缓存加载时间.

大多数存储库在重新打包之前没有很多松散的对象,但在GVFS情况下(参见" 宣布GVFS(Git虚拟文件系统) "),存储库可以增长到拥有数百万个松散对象.在一个支持GVFS的repo上使用~250万个松散对象
分析Git For Windows中的 'git log'性能,显示占用了12%的CPU时间strbuf_addf().

添加一个新的性能测试p4211-line-log.sh,对此缓存加载更敏感.
通过限制为1000次提交,我们更接近于将历史记录读入寻呼机时的用户等待时间.

对于具有两个~512 MB包文件和~572K松散对象的Linux repo的副本,运行'git log --oneline --parents --raw -1000'具有以下性能:

 HEAD~1            HEAD
----------------------------------------
 7.70(7.15+0.54)   7.44(7.09+0.29) -3.4%

更新2018年3月:Git 2.17将进一步改进git status:看到这个答案.


更新:Git 2.20(Q8 2018)添加了索引条目偏移表(IEOT),允许git status更快地加载索引.

请参阅Ben Peart()提交77ff112,提交3255089,提交abb4bb8,提交c780b9c,提交3b1d9e0,提交371ed0d(2018年10月10日). 见提交252d079通过(2018年9月26日)阮泰玉维战().(由Junio C Hamano合并- -提交e27bfaa,2018年10月19日)benpeart
pclouds
gitster

read-cache:在工作线程上加载缓存条目

此补丁通过利用索引条目偏移表(IEOT)并行地分割多个线程中的缓存条目的加载和转换,从而有助于解决加载索引的CPU成本问题.

我曾经p0002-read-cache.sh生成一些性能数据:

Test w/100,000 files reduced the time by 32.24%
Test w/1,000,000 files reduced the time by -4.77%

请注意,在1,000,000个文件的情况下,多线程缓存条目解析不会产生性能提升.这是因为在此repo中解析索引扩展的成本远远超过加载缓存条目的成本.

这允许:

config:添加新的index.threads配置设置

添加对新index.threads配置设置的支持,该设置将用于控制线程代码do_read_index().

值为0将告诉索引代码自动确定要使用的正确线程数.
值为1将使代码单线程化.

大于1的值将设置要使用的最大线程数.

出于测试目的,可以通过将GIT_TEST_INDEX_THREADS=环境变量设置为大于0的值来覆盖此设置 .


Git 2.21(2019年第一季度)引入了一项新的改进,更新了松散的对象缓存,用于优化已更新的存在查找.

见提交8be88db(2019年1月7日),并提交4cea1ce,提交d4e19e5,提交0000d65(2019年1月6日),由勒内Scharfe( )rscharfe.
(由Junio C gitsterHamano合并- -在提交eb8638a,2019年1月18日)

object-store:oid_array每个子目录使用一个松散缓存

根据需要,松散对象缓存一次填充一个子目录.
它存储在一个中oid_array,必须在每次添加操作后使用.
因此,在查询各种对象时,部分填充的阵列最多需要使用255次,这比排序一次要多100倍.

oid_array每个子目录使用一个.
这确保了条目必须只进行一次排序.
它还避免了每个缓存查找的八个二进制搜索步骤作为小额奖励.

缓存用于碰撞检查日志占位符%h,%t并且%p,我们可以看到的变化加快了他们在大约一库 每个子目录100个对象:

$ git count-objects
26733 objects, 68808 kilobytes

Test                        HEAD^             HEAD
--------------------------------------------------------------------
4205.1: log with %H         0.51(0.47+0.04)   0.51(0.49+0.02) +0.0%
4205.2: log with %h         0.84(0.82+0.02)   0.60(0.57+0.03) -28.6%
4205.3: log with %T         0.53(0.49+0.04)   0.52(0.48+0.03) -1.9%
4205.4: log with %t         0.84(0.80+0.04)   0.60(0.59+0.01) -28.6%
4205.5: log with %P         0.52(0.48+0.03)   0.51(0.50+0.01) -1.9%
4205.6: log with %p         0.85(0.78+0.06)   0.61(0.56+0.05) -28.2%
4205.7: log with %h-%h-%h   0.96(0.92+0.03)   0.69(0.64+0.04) -28.1%



4> Chris Kline..:

一个长期解决方案是增加git以在内部缓存文件系统状态.

Karsten Blees已经为msysgit做了这样的事情,它大大提高了Windows的性能.在我的实验中,他的更改花费了我在Win7机器上运行的"git status"从25秒到1-2秒的时间.

Karsten的变化:https://github.com/msysgit/git/pull/94

讨论缓存方法:https://groups.google.com/forum/#!topic / msysgit/fL_jykUmUNE/discussion


为了跟进这一点:Karsten的更改现已添加到官方msysgit发行版中.
推荐阅读
php
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有