3 回答

TA贡献1993条经验 获得超5个赞
简介:
Git的pack文件经过精心构造,可以有效地使用磁盘缓存,并为常用命令和读取最近引用的对象提供“不错”的访问模式。
Git的包文件格式相当灵活(见文档/技术/包,format.txt,或将打包文件在Git的社区图书)。打包文件以两种主要方式存储对象:“未删除”(获取原始对象数据并进行压缩压缩)或“删除”(针对某个其他对象形成增量,然后对生成的增量数据进行压缩压缩)。数据包中存储的对象可以按任何顺序排列(不必(不必)按对象类型,对象名称或任何其他属性排序),并且可以针对相同类型的其他任何合适的对象制作已删除的对象。
Git的pack-objects命令使用了几种启发式方法,可以为常见命令提供出色的参考位置。这些启发式方法既控制了已删除对象的基础对象的选择,又控制了对象的顺序。每种机制大部分都是独立的,但是它们有一些共同的目标。
Git确实形成了增量压缩对象的长链,但是试探法试图确保只有“旧”对象在长链的末端。core.deltaBaseCacheLimit自动使用增量基本缓存(其大小由配置变量控制 ),并且可以大大减少需要读取大量对象(例如git log
-p)的命令所需的“重建”次数。
增量压缩启发式
典型的Git存储库存储大量对象,因此无法合理地比较所有对象以找到将产生最小增量表示形式的对(和链)。
增量基数选择启发式算法是基于这样的思想,即可以在文件名和大小相似的对象中找到良好的增量基数。每种类型的对象都是单独处理的(即,一种类型的对象永远不会用作另一种类型的对象的增量基础)。
出于增量基数选择的目的,对象(主要)按文件名和大小排序。进入此排序列表的窗口用于限制被视为潜在增量基础的对象数量。如果一个“足够好” 1个没有找到在其窗口中的对象之间的对象增量表示,则该对象将不被增量压缩。
窗口的大小由的--window=选项 git pack-objects或pack.window配置变量控制。增量链的最大深度由的--depth= 选项git pack-objects或pack.depth配置变量控制。该--aggressive选项git gc极大地增加了窗口大小和最大深度,以尝试创建较小的打包文件。
文件名排序会将名称相同(或至少类似结尾(例如.c))的条目的对象聚在一起。大小排序从最大到最小,因此删除数据的增量要优先于添加数据的增量(因为删除增量具有较短的表示形式),因此较早,较大的对象(通常是较新的)倾向于以普通压缩方式表示。
1 什么才算是“足够好”取决于所讨论对象的大小及其潜在的增量基数以及其产生的增量链的深度。
对象排序启发式
对象以“最近引用”的顺序存储在打包文件中。重建最新历史记录所需的对象放在包装中的较早位置,它们将靠近在一起。这通常适用于OS磁盘缓存。
所有提交对象均按提交日期排序(最新的优先),并存储在一起。此放置和排序优化了遍历历史图和提取基本提交信息(例如git log)所需的磁盘访问。
从第一个存储的(最新的)提交开始,从树开始存储tree和blob对象。每棵树以深度优先的方式进行处理,存储所有尚未存储的对象。这会将重建最近提交所需的所有树木和斑点都放在一个位置。接下来,将按照已排序的提交顺序存储尚未保存但以后提交需要的所有树和Blob。
最终对象的排序受增量基本选择的影响很小,因为如果为增量表示选择了一个对象并且尚未存储其基本对象,则将其基本对象存储在已修改对象本身之前。这样可以防止由于读取基础对象所需的非线性访问而导致磁盘高速缓存丢失,而该基础对象后来将“自然地”存储在打包文件中。

TA贡献1858条经验 获得超8个赞
打包文件中增量存储的使用只是实现细节。在那个级别上,Git不知道为什么或从某一个修订版本到下一个版本如何进行更改,而是只知道blob B与blob A非常相似,除了这些更改C。因此,它只会存储blob A并更改C (如果选择这样做-它也可以选择存储Blob A和Blob)。
从打包文件中检索对象时,增量存储不会暴露给调用方。呼叫者仍然看到完整的斑点。因此,在不优化增量存储的情况下,Git的工作方式与以往一样。

TA贡献1865条经验 获得超7个赞
正如我在“ git的瘦包是什么? ”中提到的那样。
Git仅在packfile中进行删除
我在“ git二进制差异算法(增量存储)是否标准化? ”中详细介绍了用于打包文件的增量编码。
另请参阅“ git何时以及如何使用增量存储? ”。
请注意core.deltaBaseCacheLimit,对于Git 2.0.x / 2.1(2014年第三季度),控制打包文件默认大小的配置很快将从16MB增加到96MB。
参见David Kastrup(2014年5月)的commit 4874f54:
将core.deltaBaseCacheLimit碰撞到96m
默认值16m会导致大型delta链和大型文件的严重抖动。
以下是一些基准测试(的pu变体git blame):
time git blame -C src/xdisp.c >/dev/null
用于git gc --aggressive在SSD驱动器上重新打包的Emacs存储库(v1.9,导致窗口大小为250)。
有问题的文件大约有30000行,大小为1Mb,历史记录约为2500次提交。
16m (previous default):
real 3m33.936s
user 2m15.396s
sys 1m17.352s
96m:
real 2m5.668s
user 1m50.784s
sys 0m14.288s
- 3 回答
- 0 关注
- 1448 浏览
添加回答
举报