重新打包存储库对大型二进制文件有用吗?

时间:2018-06-23 00:21:37

标签: git compression

我正在尝试将大量历史记录从Perforce转换为Git,并且一个文件夹(现为git分支)包含大量的大型二进制文件。我的问题是我在运行git gc --aggressive时内存不足。

我在这里的主要问题是,重新打包存储库是否可能对大型二进制文件产生任何有意义的影响。再压缩20%会很棒。 0.2%不值得我付出努力。如果没有,我将按照建议的here跳过它们。

作为背景,我成功地使用了git p4并以自己满意的状态创建了存储库,但这在幕后使用了git fast-import,所以我想在正式使用存储库之前对其进行优化,并且确实进行任何提交都会自动触发缓慢的gc --auto。裸露状态下目前大约有35GB。

从概念上讲,该二进制文件似乎是嵌入式设备中使用的供应商固件。我认为400-700MB范围内大约有25个,而20-50MB范围内可能还有数百个。它们可能是磁盘映像,但我不确定。随着时间的推移,版本和文件类型多种多样,我经常看到.ziptgz.simg文件。因此,我希望原始代码有很多重叠,但是我不确定此时实际文件的外观如何相似,因为我相信这些格式已经被压缩了,对吧?

这些二进制文件包含在一个(旧的)分支中,该分支将很少被过度使用(以至于质疑版本控制是完全有效的,但超出了范围)。当然,该分支的性能不需要很高。但是我希望存储库的其余部分合理。

欢迎提供其他有关最佳包装或内存管理的建议。我承认我不太了解链接问题上讨论的各种git选项。我也不真正了解--window中的--depthgit repack标志在做什么。但是主要的问题是二进制文件本身的重新包装是否在做有意义的事情。

2 个答案:

答案 0 :(得分:4)

  

我在这里的主要问题是,重新打包存储库是否会对大型二进制文件产生有意义的影响。

这取决于它们的内容。对于您专门概述的文件:

  

我经常看到.zip,tgz和.simg文件。

Zipfiles和tgz(压缩的tar归档文件)文件已经被压缩,并且具有可怕的(即高)Shannon entropy值(对于Git而言是可怕的),并且不会相互压缩。 .simg个文件可能是Singularity disk image files(我必须在这里猜)。我不知道它们是否被压缩以及如何被压缩,但是我认为它们是被压缩的。 (一个简单的测试是将一个文件供入gzip之类的压缩器,然后查看它是否收缩。)

  

这样,我希望原始代码有很多重叠,但是我不确定此时实际文件的外观如何相似,因为我相信这些格式已经被压缩了,对吧?

精确地。因此,将它们未压缩存储在Git中,反而会导致最终更大的压缩。 (但是打包可能需要大量内存。)

  

如果[这可能是徒劳的],我将按照建议的here将其跳过。

那是我第一次来这里。 :-)

  

我承认我不太了解链接问题上讨论的各种git选项。我也不了解--window中的--depthgit repack标志在做什么。

各种限制令人迷惑(和充斥)。同样重要的是要意识到,它们不会在克隆上被复制,因为它们位于.git/config(这不是已提交的文件)中,因此新的克隆不会将其拾取。 .gitattributes文件 已复制到克隆上,新的克隆将继续避免打包不可打包的文件,因此这是一种更好的方法。

(如果您想深入了解这些细节,可以在the Git technical documentation中找到一些细节。这里并没有精确讨论窗口的大小,但是它与Git用于存储以下内容的内存有关-在选择可能彼此很好压缩的对象时映射对象数据,有两个:一个用于一个包文件中的每个单独的贴图,一个用于所有包文件中的总计总mmap。在链接上未提及:{{1} },即用来存储增量基数的内存,但是要了解这一点,您需要使用增量压缩和增量链, 1 并阅读相同的技术文档。请注意,Git默认为不会尝试打包任何大小超过core.deltaBaseCacheLimit的文件对象。各种core.bigFileThreshold控件稍微复杂一点:打包通过多线程完成,以尽可能利用所有CPU,每个线程可能会使用大量内存。限制线程数会限制总内存使用量:如果一个线程要使用256 MB,则8个线程可能会使用8 * 256 = 2048 MB或2 GB。位图主要是加快从繁忙服务器获取数据的速度。)


1 它们并不那么复杂:当一个对象说“获取对象XYZ并应用这些更改”,但是对象XYZ本身说“获取对象PreXYZ并应用这些更改”时,就会发生增量链。 。对象PreXYZ也可以获取另一个对象,依此类推。 delta base 是此列表底部的对象。

答案 1 :(得分:0)

  

欢迎其他有关最佳包装或内存管理的建议。

Git 2.20(2018年第四季度)将有一个:当存储库中的packfile太多(不推荐)时,在其中查找对象将需要查询许多pack .idx文件; 引入了一种新的机制,使单个文件可以合并所有.idx个文件

请参见commit 6a22d52commit e9ab2edcommit 454ea2ecommit 0bff526commit 29e2016commit fe86c3bcommit c39b02a,{{3} },commit 2cf489a(2018年8月20日)作者:commit 6d68e6a
(由Derrick Stolee (derrickstolee)Junio C Hamano -- gitster --中合并,2018年9月17日)

  

pack-objects:考虑多包索引中的包

     

运行'git pack-objects --local'时,我们要避免打包备用对象。
  当前,我们使用packed_git_mru列表检查这些对象,该列表不包括multi-pack-index覆盖的打包文件。

有一个新设置:

core.multiPackIndex::
     

使用multi-pack-index文件使用单个索引跟踪多个packfile。

还有commit 49f210fmulti-pack index is explained here中的内容:

多包索引(MIDX)设计说明

  

Git对象目录包含一个“ pack”目录,其中包含:

  • 打包文件(后缀“ .pack”)和
  • 打包索引(后缀为“ .idx”)。
  

pack-indexes提供了一种查找对象并导航到包中其偏移量的方法,但是这些对象必须与packfile成对使用。
  配对取决于文件名,因为pack-index仅在带有后缀的pack-file中有所不同。

     

虽然pack-indexs提供了每个packfile的快速查找,但是随着packfile数量的增加,这种性能会降低,因为缩写需要检查每个packfile,而我们最有可能会错过最近使用的packfile。 / p>      

对于某些大型存储库,由于存储空间或重新包装时间过长而无法将其重新包装为单个packfile。

     

multi-pack-index (简称为 MIDX )将对象列表及其偏移量存储到多个packfile中。
  它包含:

     
      
  • 打包文件名称列表。
  •   
  • 对象ID的排序列表。
  •   
  • 第i个对象ID的元数据列表,包括:      
        
    • 指向第j个打包文件的值j。
    •   
    • 对象在第j个压缩文件中的偏移量。
    •   
  •   
  • 如果需要大的偏移量,我们使用另一个大的偏移量列表   偏移量类似于版本2的pack-indexs。
  •   
     

因此,我们可以为任意数量的packfile提供O(log N)查找时间。