快取解析是 sbt 從 0.13.7 開始新增的實驗性功能,旨在解決相依性解析的可擴展效能問題。
若要設定快取解析,請在專案的建置中包含以下設定
updateOptions := updateOptions.value.withCachedResolution(true)
專案使用 libraryDependencies
設定宣告其自身的函式庫相依性。您加入的函式庫也會引入其傳遞相依性。例如,您的專案可能相依於 dispatch-core 0.11.2;dispatch-core 0.11.2 相依於 async-http-client 1.8.10;async-http-client 1.8.10 相依於 netty 3.9.2.Final,依此類推。如果我們將每個函式庫視為一個節點,並以箭頭指向相依的節點,我們可以將整個相依性視為一個圖形 — 具體而言是一個有向無環圖。
這種圖形狀結構(採用自 Apache Ivy)允許我們以傳遞方式定義覆寫規則和排除規則,但隨著節點數量的增加,解析相依性所需的時間會顯著增長。請參閱本頁後面的動機章節,以取得完整說明。
快取解析功能類似於增量編譯,只會重新編譯自上次 compile
以來已變更的來源。與 Scala 編譯器不同,Ivy 沒有單獨編譯的概念,因此需要實作該概念。
快取解析功能不會解析完整的相依性圖形,而是建立迷你圖形 — 每個直接相依性都出現在所有相關子專案中。這些迷你圖形使用 Ivy 的解析引擎進行解析,結果會儲存在本機 $HOME/.sbt/1.0/dependency/
下(或 sbt.dependency.base
旗標指定的位置),並在所有建置之間共用。解析所有迷你圖形後,會套用衝突解析演算法(通常是選擇最新版本)將它們縫合在一起。
當您將新的函式庫新增至專案時,快取解析功能會在 $HOME/.sbt/1.0/dependency/
下檢查迷你圖形檔案,並載入先前解析的節點,這會產生可忽略的 I/O 負擔,並且只會解析新加入的函式庫。預期的效能改進是,第二個和第三個子專案可以利用第一個子專案中解析的迷你圖形,並避免重複工作。下圖說明專案 A、B 和 C,它們都命中同一組 json 檔案。
實際的加速效果會因案例而異,但如果您有很多子專案,應該會看到明顯的加速效果。來自用戶的初步報告顯示,從 260 秒變更為 25 秒。您的結果可能會有所不同。
快取解析是實驗性功能,您可能會遇到一些問題。當您看到這些問題時,請向 GitHub Issue 或 sbt-dev 列表報告。
第一次執行時,快取解析可能會很慢,因為它需要解析所有迷你圖形,並將結果儲存到檔案系統中。每當您新增系統未見過的新節點時,它都會儲存迷你圖形。第二次執行起應該會更快,但將完整解析的 update
與第二次執行起進行比較可能不是公平的比較。
Ivy 的某些行為沒有意義,尤其是在 Maven 模擬方面。例如,它似乎將 Maven 發佈的函式庫引入的所有傳遞相依性都視為 force()
,即使原始的 pom.xml
沒有說明也一樣。
$ cat ~/.ivy2/cache/com.ning/async-http-client/ivy-1.8.10.xml | grep netty
<dependency org="io.netty" name="netty" rev="3.9.2.Final" force="true" conf="compile->compile(*),master(*);runtime->runtime(*)"/>
在使用不同的 Maven 分類器的多個相依性到同一個函式庫時,也存在一些問題。在這些情況下,重現與正常 update
完全相同的結果可能沒有意義或根本不可能。
當迷你圖形包含 SNAPSHOT 或動態相依性時,該圖形會被視為動態,並且會在單個任務執行後失效。因此,如果您的圖形中有任何 SNAPSHOT,您的體驗可能會降低。(這在未來可能會改進)
名為 updateOptions
的設定鍵使用 update
任務自訂受管理的相依性解析的詳細資料。它的其中一個旗標稱為 latestSnapshots
,它會控制鏈結解析器的行為。在 0.13.6 之前,sbt 會選擇它在鏈結中找到的第一個 -SNAPSHOT
修訂版本。當啟用 latestSnapshots
時(預設值:true
),它會查看鏈結中的所有解析器,並使用發佈日期進行比較。
如果您在建置中有很多遠端儲存庫,或者您住在伺服器很遠的地方,那麼取捨的結果可能是更長的解析時間。因此,以下是如何停用它
updateOptions := updateOptions.value.withLatestSnapshots(false)
sbt 內部使用 Apache Ivy 來解析函式庫相依性。儘管多年來 sbt 受益於不必重新發明自己的相依性解析引擎,但我們越來越看到可擴展性方面的挑戰,尤其是在具有多個子專案和大型相依性圖形的專案中。sbt 的解析可擴展性涉及多個因素
在上述因素中,影響最大的是傳遞節點的數量。
排除和覆寫規則會以傳遞方式套用,因此每當圖形中引入新節點時,它都需要檢查其父節點的規則、祖父節點的規則、曾祖父節點的規則等。
sbt 將組態和子專案視為獨立的相依性圖形。這允許我們為不同的組態和子專案包含任意函式庫,但如果相依性解析速度緩慢,線性縮放就會開始產生損害。先前曾嘗試快取函式庫相依性的結果,但當 libraryDependencies
變更時,仍然會導致完整解析。