Git对于100,000个对象来说确实很慢。 任何修复?

我有一个“新鲜的”git-svn回购(11.13 GB),其中有超过100,000个对象。

我已经预演了

git fsck git gc 

在初始结账后回购。

然后,我试图做一个

 git status 

做git状态的时间是2m25.578s到2m53.901s

我通过发出命令testing了git的状态

 time git status 

5次,全部在上述两次之间进行。

我在Mac OS X上执行此操作,本地不通过VM。

没有办法,应该采取这么久。

有任何想法吗? 帮帮我?

谢谢。

编辑

我有一个同事坐在我旁边的一个可比较的盒子。 更less的内存和运行Debian与jfs文件系统。 他的git状态在同一个仓库中运行.3(这也是一个git-svn结帐)。

另外,我最近改变了我的文件权限(到777)在这个文件夹,它带来了相当大的时间(为什么,我不知道)。 现在我可以在3到6秒之间完成任务。 这是可控的,但仍然是一个痛苦。

下面是我现在可以看到的几个项目。

  1. git gc --aggressive
  2. 打开文件权限777

还有其他事情正在发生,但这是最明显的影响。

git状态必须每次查看存储库中的每个文件。 你可以告诉它停止看你不在的树木

 git update-index --assume-unchanged <trees to skip> 

资源

从手册:

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

这个选项也可以作为一个粗略的文件级机制来忽略被跟踪文件中未提交的变化(类似于.gitignore对未跟踪文件所做的)。 如果需要在索引中修改这个文件,Git会失败(优雅地),例如,在提交时合并; 因此,如果假设未跟踪的文件在上游发生更改,则需要手动处理该情况。

git中的许多操作都依赖于你的文件系统来实现一个有效的lstat(2)实现,因此可以便宜地检查工作树文件的st_mtime信息,以查看文件内容是否从索引文件中logging的版本发生了变化。 不幸的是,一些文件系统的低效率lstat(2)。 如果你的文件系统是其中的一个,你可以将“假设不变”位设置为你没有改变的path,使git不做这个检查。 请注意,在path上设置这个位并不意味着git会检查文件的内容,看看它是否发生了变化 – 它使git忽略任何检查,并假定它没有改变。 当对工作树文件进行更改时,必须在修改之前或之后,通过删除“假定不变”位来明确地告诉git。

为了设置“不变”位,使用–assume-unchanged选项。 要取消设置,请使用–no-assume-unchanged。

该命令查看core.ignorestatconfigurationvariables。 当这是真的,path更新与git update-indexpath…和path更新与其他git命令,更新索引和工作树(例如git apply –index,git checkout-index -u和git read-tree -u )自动标记为“假定不变”。 请注意,如果git update-index –refresh发现工作树文件与索引相匹配,则不会设置“假定不变”位(如果要将它们标记为“假定不变”,请使用git update-index –really-refresh)。


现在,很明显,只有存在可以方便地忽略的回购部分时,该解决scheme才会起作用。 我在一个类似规模的项目上工作,我肯定不需要定期检查大树。 git-status的语义使它成为一个普遍的O(n)问题(n个文件)。 您需要特定于域的优化才能做得更好。

请注意,如果以拼接模式工作,也就是说,如果通过合并而不是rebase从上游集成更改,则此解决scheme变得不太方便,因为从上游合并的–assume-unchanged对象的更改将成为合并冲突。 您可以通过重定位工作stream程避免此问题。

一个长期的解决scheme是增强git来caching内部的文件系统状态。

Karsten Blees为msysgit做了这样的工作,大大提高了Windows的性能。 在我的实验中,他的改变花费了我的Win7机器上运行在VM上的25秒到1-2秒的“git status”时间。

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

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

一般来说,我的mac可以用git,但是如果有很多松散的对象,那么它会变得非常慢。 看起来hfs在单个目录下有很多文件不太好。

 git repack -ad 

其次是

 git gc --prune=now 

将制作一个单一的包文件,并删除任何遗留物体。 运行这些可能需要一些时间。

你可以尝试通过--aggressive开关git gc ,看看是否有帮助:

 # this will take a while ... git gc --aggressive 

另外,你可以使用git filter-branch来删除旧提交和/或文件,如果你有一些你不需要的东西(比如旧的二进制文件)。

Git 2.13(Q2 2017)的git status应该更快,因为:

  • 对string优化进行优化(参见“ 改善git status性能的方法 ”)
  • 一个更好的“读取caching”pipe理。

关于最后一点,请参阅Jeff Hostetler( jeffhostetler )的 commit a33fc72 (2017年4月14日) 。
(由Junio C gitster合并- gitster – in commit cdfe138 ,2017年4月24日)

read-cache:force_verify_index_checksum

除非设置了“ force_verify_index_checksum ”全局variables,否则教git跳过validation从read_index()调用的read_index()索引文件末尾的SHA1-1校验和。

fsck强制这个validation。

校验和validation用于检测磁盘损坏情况,而对于小型项目,计算SHA-1所花费的时间并不是那么重要,但是对于庞大的存储库,这种计算会为每个命令增加大量时间。


Git 2.14通过更好地考虑到“ 未跟踪的caching ”来改善git状态性能,这允许Git使用stat结构的mtime字段跳过未读跟踪的目录(如果它们的数据没有改变)。

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

参见David Turner( dturner-tw )的 commit edf3b90 (2017年5月8日) 。
(由Junio C gitster合并- gitster – in fa0624f ,2017年5月30日)

当“ git checkout ”,“ git merge ”等操作内核索引时,索引扩展中的各种信息被从原始状态中丢弃,因为通常情况下它们不是保持最新状态,date并与主索引上的操作同步。

未跟踪的caching扩展现在被复制到这些操作中,这将加快“git状态”(只要caching正确无效)。


更一般地说,使用Git 2.14.x / 2.15写入caching的速度也会更快

见Kevin Willford(“) 提交ce012de , 提交b50386c , 提交3921a0b (2017年8月21日) 。
(由Junio C gitster合并- gitster – in commit 030faf2 ,2017年8月27日)

我们曾经花费超过必要的周期分配和释放一块内存,同时写入每个索引项。
这已经被优化了。

当这个指数超过一百万个条目,并且在小回购时没有性能下降时,这个节省将在3-7%之间。

对于它的价值,我最近发现我的主和开发分支之间的git status命令之间有很大的差异。

长话短说,我把这个问题追溯到项目根目录中的一个280MB文件。 这是一个意外的数据库转储签入,所以删除它是好的。

以下是之前和之后:

 ⚡ time git status # On branch master nothing to commit (working directory clean) git status 1.35s user 0.25s system 98% cpu 1.615 total ⚡ rm savedev.sql ⚡ time git status # On branch master # Changes not staged for commit: # (use "git add/rm <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # deleted: savedev.sql # no changes added to commit (use "git add" and/or "git commit -a") git status 0.07s user 0.08s system 98% cpu 0.157 total 

我有105,000个存储对象,但是似乎大文件比许多小文件更具威胁性。

你也可以尝试git repack

也许你使用病毒扫描程序? 我在Windows和Linux上testing了一些大的项目 – 这真是太快了!

我不认为你需要做一个克隆回购的git gc(它应该是干净的)。

你的硬盘好吗? IOPS和R / W每秒? 也许它被损坏了?

也许聚光灯正试图索引文件。 也许禁用你的代码目录的焦点。 检查Activity Monitor并查看正在运行的进程。

我会创build一个使用不同文件系统的分区。 与其他文件系统上的类似操作相比,HFT +对我来说一直很慢。

尝试运行Prune命令,它将被删除,松散的对象

git远程修剪起源