3 回答

TA貢獻1993條經驗 獲得超6個贊
簡介:
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 關注
- 1520 瀏覽
添加回答
舉報