首頁 > 軟體

Github的清點物件演算法

2020-06-16 17:52:15

$ git clone https://github.com/torvalds/linux
Cloning into 'linux'...
remote: Counting objects: 4350078, done.
remote: Compressing objects: 100% (4677/4677), done.
Receiving objects:  4% (191786/4350078), 78.19 MiB | 8.70 MiB/s

段提示說,遠端程式碼庫一共有 4350078 個物件需要克隆。

這就叫"清點物件"(counting objects),Github 需要實時計算出來,需要克隆的物件總數。

這個過程非常慢,根據 Github 的披露,像 Linux kernel 這樣巨大的庫,清點一次需要 8 分鐘!也就是說,發出git clone命令後,會乾等八分鐘,然後才會開始真正的資料傳輸。這當然是無法忍受的。Github 團隊一直想解決這個問題。

後來,他們終於發現了一種新的演算法,現在清點一次只要 3 毫秒!

為了理解這個演算法,你必須先知道,什麼是 Git 的物件。簡單說,物件就是檔案,最重要的物件有三種。

快照物件(Commit)
目錄物件(Directory)
檔案物件(File)

每次提交程式碼的時候,會生成一個 commit 物件,裡面有對應的當前"目錄物件"的名字。"目錄物件"儲存了程式碼根目錄所含有的子目錄和檔案資訊。每一個子目錄就是另一個"目錄物件",每一個檔案則是"檔案物件",裡面是具體的檔案內容。

所以,"清點物件"就是清點各種 commit、目錄、檔案等。git clonegit fetch操作都需要清點物件,因為需要知道,到底下載哪些物件檔案。

清點物件的原始演算法如下。

  1. 列出本地所有分支最新的一個 commit
  2. 列出遠端所有分支最新的一個 commit
  3. 兩者進行比較,只要有不同,就意味著分支發生變動
  4. 每一個發生變動的 commit,都清點其中具體變動的子目錄和檔案
  5. 追溯到當前 commit 的父節點,重複第四步,直至本地與遠端的歷史一致為止
  6. 加總所有需要變動的物件

上面的過程說明,"清點物件"是一個檔案遍歷演算法,變動的物件會被一一清點到,這就意味著大量的檔案讀操作。對於大型程式碼庫來說,這個過程非常慢。

Github 團隊想到的新演算法,是建立一個 Bitmap 索引,即為每一個 commit 生成一個二進位制值。

開啟本地 Github 倉庫的.git/objects/pack/目錄,你會看到一個索引檔案和一個資料檔案,它們就是 Bitmap。簡單說,這兩個檔案索引了當前程式碼庫的所有物件,然後使用一個二進位制值代表這些物件。有多少個物件,這個二進位制值就有多少位。它的第n位,就代表資料檔案裡面的第n個物件。

每個 commit 都會有一個對應的二進位制值,表示當前快照包含的所有物件。這些物件對應的二進位制位都為1,其他二進位制位都為0。

這樣做的好處是,不用讀取 commit 物件,只要讀取這個二進位制值,就會知道當前 commit 包含了哪些節點。更妙的是,兩個二進位制值只要做一次 XOR 運算,就會知道哪些位(即哪些物件)發生了變動。而且,因為新的物件總是新增到現有二進位制位的後面,所以只要讀取多出來的那些位,就知道當前 commit 比上一次 commit 多出了哪些物件。

這樣一來,"清點物件"就變成了二進位制值的比較運算,因此速度極快。進一步的介紹,請參看官方文件《Bitmap 的解釋》《Bitmap 的格式》

目前,Github 的生產環境已經部署了這套演算法,使用者再也不用為了清點物件,而苦苦等待了。而且,Github 團隊還把它合併進了 Git,這意味著,從此所有 Git 實現都可以使用 Bitmap 功能了,因此將來肯定還會有更多好玩的用法出現。

GitHub 教學系列文章: 

通過GitHub建立個人技術部落格圖文詳解  http://www.linuxidc.com/Linux/2015-02/114121.htm

GitHub 使用教學圖文詳解  http://www.linuxidc.com/Linux/2014-09/106230.htm 

Git 標籤管理詳解 http://www.linuxidc.com/Linux/2014-09/106231.htm 

Git 分支管理詳解 http://www.linuxidc.com/Linux/2014-09/106232.htm 

Git 遠端倉庫詳解 http://www.linuxidc.com/Linux/2014-09/106233.htm 

Git 本地倉庫(Repository)詳解 http://www.linuxidc.com/Linux/2014-09/106234.htm 

Git 伺服器搭建與用戶端安裝  http://www.linuxidc.com/Linux/2014-05/101830.htm 

Git 概述 http://www.linuxidc.com/Linux/2014-05/101829.htm 

分享實用的GitHub 使用教學 http://www.linuxidc.com/Linux/2014-04/100556.htm 


IT145.com E-mail:sddin#qq.com