本文經許可從原始位置 http://blogs.collab.net/subversion/reducing_network_traffiic_in_subversion_1-8 複製。已移除或更新失效的連結。
作者:C. Michael Pilato
摘要:建立在 Subversion 1.7 中發布的 WC-NG 基礎上,如果檔案內容已存在於本機原始儲存區中,儲存庫存取模組 libsvn_ra_serf 可以顯著減少 svn switch
和 svn update
的網路流量。
張貼 2012-10-24
這篇文章討論了 Apache Subversion 功能,這些功能在撰寫本文時已在開發程式碼庫中提供,但尚未在官方版本中發布,並且在發布之前可能會變更。
我既不為我喜愛 Subversion 的稀疏檢出功能道歉,也不試圖隱藏這個事實。該功能一推出,我就將我本地的 Subversion 版本專案從散亂的三十多個不同的主幹和分支工作副本,重新整理成每個專案一個工作副本,根目錄設在專案的根目錄,並從那裡稀疏填充。
現在,我坦白說。立竿見影的好處(至少對我來說)大多是軟性的,對 Subversion 為我所做的事情沒有那麼多無形的改善,而是對我在 Subversion 操作之間所做的事情有改善。我的工作空間組織得更好。我花較少時間試圖記住哪些工作副本包含哪些內容。我只要執行一個涵蓋所有這些區域的單一更新,就能夠對我在意的專案樹部分中發生的事情有更好的全盤了解。這些都不是你可以用基準測試工具或回歸測試套件來衡量的,它們是由我原本混亂的大腦中,暴露的表面積增加的百分比來衡量的。
Subversion 開發人員在 Subversion 1.5 中首次推出稀疏檢出,並在後續版本中對其進行了一些改進。例如,Subversion 1.6 具備排除功能,也就是說可以「取消望遠鏡」現有的工作副本成員。現在你不再需要刪除和重建包含你不再感興趣的子樹的工作副本。Subversion 的合併和合併追蹤功能(後者也是在 Subversion 1.5 中引入的)也進行了改進,以便在涉及稀疏填充的工作副本時,它們的行為符合預期。
Subversion 1.7 為 Subversion 整體帶來了另一個有用的改進。重新設計工作副本管理區域(無論是在儲存機制或程式設計介面方面)的部分目的是為了激發新功能開發。WC-NG(這是新工作副本概念的名稱)大幅改寫了組織和存取工作副本元資料的方式,而正如所預期的,它的幾個特性引起了我的注意。首先,WC-NG 會將所有版本化檔案的快取原始文字基礎副本移到單一位置,並根據其 SHA-1 檢查碼建立索引。為了最佳化磁碟使用率,如果存在相同內容的重複副本,只會保留單一副本。我可能比 Subversion 的客戶端行為更常開發 Subversion 的儲存庫和儲存庫存取功能,因此對我而言,這裡存在著某種顯而易見的對稱性:Subversion 儲存庫也會使用以 SHA-1 檢查碼為鍵的索引追蹤檔案內容,也會嘗試只保留檔案內容的特定「表示」的單一副本。其次,WC-NG 不會預先清除不再絕對必要的原始文字基礎(因為它們與目前的工作副本狀態無關)。相反地,這些原始版本會隨著時間累積,而使用者可以執行 svn cleanup
來強制 Subversion 將儲存的原始文字基礎與目前的工作副本狀態進行對應,並捨棄不必要的原始文字基礎。
在 Subversion 1.7 發行週期接近尾聲時,我察覺到一個機會,我教導 Subversion 的 mod_dav_svn Apache 伺服器模組,讓它告知要求更新(或結帳、切換、合併、比對等)的用戶端,它建議或提供給用戶端的任何檔案內容的 SHA-1 校驗和。 (伺服器自 Subversion 1.0 之前就已傳輸此內容的 MD5 校驗和,但我們一直嘗試將專案轉換為 SHA-1。)我還不確定用戶端會如何處理這些資訊,但對我來說,以及察覺到相同情況的其他 Subversion 開發人員來說,這似乎很有價值。
在 Subversion 1.7 發行後,我終於能夠填補空白。 Subversion 1.8 預計將隨附單一 HTTP 儲存庫存取模組 libsvn_ra_serf。 Serf 對 HTTP 通訊的方法與我們之前基於 Neon 的方法不同,在於它偏好使用許多小型的管線式要求,而不是較少的同步式大型要求。使用 libsvn_ra_serf 執行的結帳和更新會要求伺服器提供更新報告,其中包含用戶端需要從伺服器擷取的清單(也就是購物清單),才能完成更新程序。 在 Subversion 1.7 中,我教導伺服器在購物清單中包含每個所需項目的 SHA-1 校驗和(如果我們繼續類比,就是 UPC 編碼)。 現在,在 Subversion 主幹(又稱「1.8-dev」)程式碼庫中,我教導 libsvn_ra_serf 取得該 UPC 編碼,詢問 WC-NG 是否有任何檔案在「原始儲藏室」中帶有該編碼,如果有的話,直接從本機原始儲存取得檔案,而不是再向伺服器要求另一份檔案副本。(在我的初始實作後,我也教導 libsvn_ra_serf 以相同方式處理 MD5 校驗和,有效地讓此最佳化作業甚至適用於最舊的受支援 Subversion 伺服器。)
這一切代表什麼? 速度。
當使用 Subversion 1.8 透過 HTTP 進行通訊時,情況允許您下載更少的文件,甚至可能是零個文件。例如,如果您暫時將工作副本回溯到較舊的版本,然後再次更新到您先前所在的版本,Subversion 根本不必透過網路取得任何檔案的內容。除非您在回溯後執行 svn cleanup
,否則您的工作副本管理區域仍保留較新版本中檔案的原始版本。類似地,如果有人提交您在工作副本中本機擁有的檔案重新命名,Subversion 不必再次透過網路取得移動檔案的內容,因為這些內容的副本已經存在於您的本機原始文字資料庫中。
現在,我開始這篇文章,喋喋不休地談論稀疏檢出。為什麼?有什麼關聯?因為我認為在稀疏檢出中,Subversion 行為的這個小改變真的有機會發光發熱。由於原始資料庫是針對每個工作副本,因此有理由認為,使用它的儲存庫樹的區段越多,找到原本必須透過網路取得的內容的機會就越大。使用稀疏的工作副本,任何時候我需要「訂閱」專案中的新分支時,Subversion 的新功能「不取得我已經擁有的檔案內容」就能使用現有的完整原始資料庫。Subversion 應該只取得分支中沒有其他分支或工作副本中標籤的任何檔案。這與完全專注於單一分支的新檢出工作副本非常不同,在該工作副本中,原始資料庫在檢出後才會完全清空,迫使 Subversion 透過網路下載檢出集中每一個檔案。更重要的是,如果我需要排除分支或其他特定子樹,然後稍後再還原它,還原程序可以存取排除之前該子樹的原始內容,以及工作副本中其他所有項目,以便在使用網路傳輸之前從中提取資料。
以一個相對簡單但常見的情況為例。您正在處理專案的 trunk,並決定需要建立一個分支,並在更獨立的情況下進行一些開發,但您仍想追蹤 trunk。過去,大多數人會
svn copy URL NEW-URL
。svn switch
讓該副本追蹤其新分支,來縮短此步驟。)使用稀疏檢出和原始儲存來源改善,事情以類似的方式執行,但網路流量較少
svn copy URL NEW-URL
。當然,Subversion 仍使用與過去相同的基於路徑的方法來存取權限。並非因為使用者可以在特定分支上讀取檔案內容,就表示現在允許他或她知道同一檔案存在於儲存庫中其他無法讀取的區域。我所做的只是協助客戶端避免重新擷取其已在本地原始快取中擁有的檔案內容。
隨著 Apache Subversion 社群著手逐步結束 Subversion 1.8 的開發活動,我鼓勵您瀏覽專案公開的資料(例如我們的 路線圖頁面 和 1.8 發行說明,兩者都是進行中的工作),看看是否有您有興趣的功能或增強功能。或許您可以協助我們測試一些新功能,並確保這些功能在正式發行時能發揮最佳效能。
C. Michael Pilato 是 Subversion 核心開發人員,也是《使用 Subversion 進行版本控制》(O'Reilly Media) 的共同作者,以及 ViewVC 的主要維護人員。他遠距在家鄉北卡羅來納州擔任 CollabNet 的軟體工程師,並自 2001 年初以來一直是活躍的開源開發人員。Mike 是一位以身為丈夫和父親為傲的人,他熱愛旅遊、足球、與家人共度美好時光,以及這些事物的任何組合。他也享受創作和演奏音樂,並懷抱著不為人知的搖滾明星幻想。Mike 擁有北卡羅來納大學夏洛特分校的電腦科學和數學學位。