3 回答

TA貢獻(xiàn)1993條經(jīng)驗 獲得超6個贊
簡介:
Git的pack文件經(jīng)過精心構(gòu)造,可以有效地使用磁盤緩存,并為常用命令和讀取最近引用的對象提供“不錯”的訪問模式。
Git的包文件格式相當(dāng)靈活(見文檔/技術(shù)/包,format.txt,或?qū)⒋虬募贕it的社區(qū)圖書)。打包文件以兩種主要方式存儲對象:“未刪除”(獲取原始對象數(shù)據(jù)并進(jìn)行壓縮壓縮)或“刪除”(針對某個其他對象形成增量,然后對生成的增量數(shù)據(jù)進(jìn)行壓縮壓縮)。數(shù)據(jù)包中存儲的對象可以按任何順序排列(不必(不必)按對象類型,對象名稱或任何其他屬性排序),并且可以針對相同類型的其他任何合適的對象制作已刪除的對象。
Git的pack-objects命令使用了幾種啟發(fā)式方法,可以為常見命令提供出色的參考位置。這些啟發(fā)式方法既控制了已刪除對象的基礎(chǔ)對象的選擇,又控制了對象的順序。每種機制大部分都是獨立的,但是它們有一些共同的目標(biāo)。
Git確實形成了增量壓縮對象的長鏈,但是試探法試圖確保只有“舊”對象在長鏈的末端。core.deltaBaseCacheLimit自動使用增量基本緩存(其大小由配置變量控制 ),并且可以大大減少需要讀取大量對象(例如git log
-p)的命令所需的“重建”次數(shù)。
增量壓縮啟發(fā)式
典型的Git存儲庫存儲大量對象,因此無法合理地比較所有對象以找到將產(chǎn)生最小增量表示形式的對(和鏈)。
增量基數(shù)選擇啟發(fā)式算法是基于這樣的思想,即可以在文件名和大小相似的對象中找到良好的增量基數(shù)。每種類型的對象都是單獨處理的(即,一種類型的對象永遠(yuǎn)不會用作另一種類型的對象的增量基礎(chǔ))。
出于增量基數(shù)選擇的目的,對象(主要)按文件名和大小排序。進(jìn)入此排序列表的窗口用于限制被視為潛在增量基礎(chǔ)的對象數(shù)量。如果一個“足夠好” 1個沒有找到在其窗口中的對象之間的對象增量表示,則該對象將不被增量壓縮。
窗口的大小由的--window=選項 git pack-objects或pack.window配置變量控制。增量鏈的最大深度由的--depth= 選項git pack-objects或pack.depth配置變量控制。該--aggressive選項git gc極大地增加了窗口大小和最大深度,以嘗試創(chuàng)建較小的打包文件。
文件名排序會將名稱相同(或至少類似結(jié)尾(例如.c))的條目的對象聚在一起。大小排序從最大到最小,因此刪除數(shù)據(jù)的增量要優(yōu)先于添加數(shù)據(jù)的增量(因為刪除增量具有較短的表示形式),因此較早,較大的對象(通常是較新的)傾向于以普通壓縮方式表示。
1 什么才算是“足夠好”取決于所討論對象的大小及其潛在的增量基數(shù)以及其產(chǎn)生的增量鏈的深度。
對象排序啟發(fā)式
對象以“最近引用”的順序存儲在打包文件中。重建最新歷史記錄所需的對象放在包裝中的較早位置,它們將靠近在一起。這通常適用于OS磁盤緩存。
所有提交對象均按提交日期排序(最新的優(yōu)先),并存儲在一起。此放置和排序優(yōu)化了遍歷歷史圖和提取基本提交信息(例如git log)所需的磁盤訪問。
從第一個存儲的(最新的)提交開始,從樹開始存儲tree和blob對象。每棵樹以深度優(yōu)先的方式進(jìn)行處理,存儲所有尚未存儲的對象。這會將重建最近提交所需的所有樹木和斑點都放在一個位置。接下來,將按照已排序的提交順序存儲尚未保存但以后提交需要的所有樹和Blob。
最終對象的排序受增量基本選擇的影響很小,因為如果為增量表示選擇了一個對象并且尚未存儲其基本對象,則將其基本對象存儲在已修改對象本身之前。這樣可以防止由于讀取基礎(chǔ)對象所需的非線性訪問而導(dǎo)致磁盤高速緩存丟失,而該基礎(chǔ)對象后來將“自然地”存儲在打包文件中。

TA貢獻(xiàn)1858條經(jīng)驗 獲得超8個贊
打包文件中增量存儲的使用只是實現(xiàn)細(xì)節(jié)。在那個級別上,Git不知道為什么或從某一個修訂版本到下一個版本如何進(jìn)行更改,而是只知道blob B與blob A非常相似,除了這些更改C。因此,它只會存儲blob A并更改C (如果選擇這樣做-它也可以選擇存儲Blob A和Blob)。
從打包文件中檢索對象時,增量存儲不會暴露給調(diào)用方。呼叫者仍然看到完整的斑點。因此,在不優(yōu)化增量存儲的情況下,Git的工作方式與以往一樣。

TA貢獻(xiàn)1865條經(jīng)驗 獲得超7個贊
正如我在“ git的瘦包是什么? ”中提到的那樣。
Git僅在packfile中進(jìn)行刪除
我在“ git二進(jìn)制差異算法(增量存儲)是否標(biāo)準(zhǔn)化? ”中詳細(xì)介紹了用于打包文件的增量編碼。
另請參閱“ git何時以及如何使用增量存儲? ”。
請注意core.deltaBaseCacheLimit,對于Git 2.0.x / 2.1(2014年第三季度),控制打包文件默認(rèn)大小的配置很快將從16MB增加到96MB。
參見David Kastrup(2014年5月)的commit 4874f54:
將core.deltaBaseCacheLimit碰撞到96m
默認(rèn)值16m會導(dǎo)致大型delta鏈和大型文件的嚴(yán)重抖動。
以下是一些基準(zhǔn)測試(的pu變體git blame):
time git blame -C src/xdisp.c >/dev/null
用于git gc --aggressive在SSD驅(qū)動器上重新打包的Emacs存儲庫(v1.9,導(dǎo)致窗口大小為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 關(guān)注
- 1540 瀏覽
添加回答
舉報