1. 快取解析

快取解析 

快取解析是 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 檔案。


fig1

實際的加速效果會因案例而異,但如果您有很多子專案,應該會看到明顯的加速效果。來自用戶的初步報告顯示,從 260 秒變更為 25 秒。您的結果可能會有所不同。

注意事項和已知問題 

快取解析是實驗性功能,您可能會遇到一些問題。當您看到這些問題時,請向 GitHub Issue 或 sbt-dev 列表報告。

第一次執行 

第一次執行時,快取解析可能會很慢,因為它需要解析所有迷你圖形,並將結果儲存到檔案系統中。每當您新增系統未見過的新節點時,它都會儲存迷你圖形。第二次執行起應該會更快,但將完整解析的 update 與第二次執行起進行比較可能不是公平的比較。

不保證 Ivy 的忠實度 

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 或動態相依性時,該圖形會被視為動態,並且會在單個任務執行後失效。因此,如果您的圖形中有任何 SNAPSHOT,您的體驗可能會降低。(這在未來可能會改進)

名為 updateOptions 的設定鍵使用 update 任務自訂受管理的相依性解析的詳細資料。它的其中一個旗標稱為 latestSnapshots,它會控制鏈結解析器的行為。在 0.13.6 之前,sbt 會選擇它在鏈結中找到的第一個 -SNAPSHOT 修訂版本。當啟用 latestSnapshots 時(預設值:true),它會查看鏈結中的所有解析器,並使用發佈日期進行比較。

如果您在建置中有很多遠端儲存庫,或者您住在伺服器很遠的地方,那麼取捨的結果可能是更長的解析時間。因此,以下是如何停用它

    updateOptions := updateOptions.value.withLatestSnapshots(false)

動機 

sbt 內部使用 Apache Ivy 來解析函式庫相依性。儘管多年來 sbt 受益於不必重新發明自己的相依性解析引擎,但我們越來越看到可擴展性方面的挑戰,尤其是在具有多個子專案和大型相依性圖形的專案中。sbt 的解析可擴展性涉及多個因素

  • 圖形中傳遞節點(函式庫)的數量
  • 排除和覆寫規則
  • 子專案的數量
  • 組態
  • 儲存庫的數量及其可用性
  • 分類器(IDE 使用的其他來源和文件)

在上述因素中,影響最大的是傳遞節點的數量。

  1. 節點越多,版本衝突的機率就越大。衝突通常是透過選擇相同函式庫中的最新版本來解決。
  2. 節點越多,它就需要回溯以檢查排除和覆寫規則的次數就越多。

排除和覆寫規則會以傳遞方式套用,因此每當圖形中引入新節點時,它都需要檢查其父節點的規則、祖父節點的規則、曾祖父節點的規則等。

sbt 將組態和子專案視為獨立的相依性圖形。這允許我們為不同的組態和子專案包含任意函式庫,但如果相依性解析速度緩慢,線性縮放就會開始產生損害。先前曾嘗試快取函式庫相依性的結果,但當 libraryDependencies 變更時,仍然會導致完整解析。