2010-05-15 41 views
2

我在寫一個簡單的.git/*文件解析器。我涵蓋了幾乎所有東西,如對象,參考文件,打包文件等,但我遇到了一個問題。假設我有一個很大的300M存儲庫(在一個包文件中),我想找出所有改變/ some/deep/inside/file文件的提交。我現在正在做的是:git如何提取與文件關聯的提交?

  • 最後取提交
  • 找到一個文件吧:
    • 取父樹
    • 找出裏面
    • 樹遞歸地重複,直到我進入文件
    • 此外,我正在檢查文件的路上每個子文件夾的哈希值。如果其中一人是相同之前提交,我認爲文件沒有改變(因爲它的父目錄並沒有改變)
  • 然後我存儲文件的散列和取父提交
  • 再次找到文件,並檢查是否哈希發生變化
    • 如果是,那麼原來的承諾(即父前一個)被更改文件

我重複一遍又一遍聯合國直到我第一次承諾。

該解決方案有效,但它很糟糕。在更糟糕的情況下,首次搜索可能需要3分鐘(300M包)。

有什麼方法可以加快速度嗎?我儘量避免在內存中放置如此​​大的物體,但現在我沒有看到任何其他方式。甚至說,最初的記憶負荷將採取永遠:(

問候,並感謝所有幫助

+1

我很好奇 - 你爲什麼複製git代碼已經做了什麼?有沒有什麼理由你不能看代碼,看看它是如何做到這一點?(跟蹤當你運行'git log '時會發生什麼) – Cascabel 2010-05-16 00:44:01

回答

1

這是Git使用跟蹤更改特定文件的基本算法,這就是爲什麼「混帳日誌 - !一些/path/to/file.txt「是一個相對較慢的操作,與許多其他單片機系統相比,它很簡單(例如,在CVS中,P4等每個repo文件都是具有文件歷史記錄的服務器文件)

儘管評估時間不應該花太長的時間,但你必須保留在內存中的數量是非常小的,你已經提到了主要觀點:記住樹ID到達路徑以快速消除那些甚至沒有提交的提交觸摸那個su B樹。樹對象非常大,就像文件系統上的目錄一樣(不出所料)。

您是否使用包裝索引?如果你不是,那麼你基本上必須解開整個揹包才能發現這一點,因爲樹木可能處於長三角鏈的末端。如果你有一個索引,你仍然需要應用delta來獲取你的樹對象,但是至少你應該能夠快速找到它們。保留應用變量的緩存,因爲很顯然,樹重複使用相同或相似的基數是很常見的 - 大多數樹對象的變化只是改變了前一個樹對象的20個字節。所以如果爲了獲得樹T1,你必須從對象T8開始並應用Td7來獲得T7,T6 ....等等,這些其他樹T2-8將被再次引用。