大約兩年前,我發表了一篇文章,詳細的介紹了 Bing 的中央工作流引擎(XAP)從 .NET Framework 升級到 .NET 5 的過程。你可以透過這篇文章來了解 XAP 的工作原理,以及它在 Bing 全域性中的位置。從那時起,XAP 一直是微軟許多搜尋和工作流相關技術的關鍵元件,並在新的整合中發揮了核心作用,比如新的 AI 驅動的 Bing。
人們對功能和效能的期望越來越高,這意味著我們對 .NET 作為基礎設施的關鍵部分的依賴性越來越深。
在過去的兩年裡,我們是 .NET 6 和 .NET 7 的早期採用者,現在正將目光轉向 .NET 8。我們發現每個版本都比上一個版本更容易升級。作為一個核心平臺團隊,我們對每個版本的 .NET 帶來的效能提升和新功能都充滿了強烈的動力。透過積極地測試並升級到最新版本,並向 .NET 團隊提供反饋,對他們的計劃產生一定影響。
本文將重點介紹我們所做的一些主要更新和麵對的挑戰,以及我們在積極跟進最新 .NET 版本時最終取得的成果。
Hybrid No-More
當第一次升級到 .NET 5 時,我們是在一個混合模型中進行的,其中我們仍然是基於 .NET Framework 4.x 構建的,但是載入程式集並在 .NET 5 下執行。我們能夠引導自己和我們的內部合作伙伴,在保持構建簡單的同時確保一些關鍵的向後相容性,但仍然利用新的執行時。
在我們升級到 .NET 6 之前,我們遷移到了一個多目標系統,直接針對 .NET Framework 和 .NET 5 進行構建。透過一些條件編譯,我們可以開始採用新的 API 來獲得一些效能優勢。到目前為止,我們已經完全棄用了 .NET Framework,並且把精力完全集中在新的執行時上。
.NET 6
隨著我們完成了從 .NET Framework 的升級,我們預計遷移到 .NET 6 會更容易。然而,仍然有一些小挑戰和一些意想之外的收穫,等下會詳細說明。
在測試期間,我們注意到一些後端 HTTP 呼叫的問題。事實證明,SocketHttpHandler 的變化使實現更符合規範,但並沒有能夠靈活地處理產生錯誤負載的錯誤伺服器。.NET 團隊修改了程式碼,使它相容性更強。
我們遇到的另一個有趣的執行時問題是一個罕見的旋轉計數 bug。它表現為在單個資料中心(可能是因為特定的硬體和流量配置)中,偶爾出現非常高的延遲峰值和較低的整體可用性。實際上,在我們提出這個問題時,. NET 團隊已經修復了它。在應用修復之後,我們看到可用性有了明顯且直接的提升:
這兩個問題都解決後,釋出基本上就很簡單了,我們只需要比較少的程式碼更改。最終,整體效能全面提升了約 5%。還有一個方面的改進比這要顯著得多:啟動時間。
當程式啟動時,它會載入幾千個程式集。所有這些程式碼都需要 jitted,最好是在真正的使用者查詢到達之前。多年來,我們已經迭代了許多技術來實現這一點,但目前的方法是透過分析 JIT 事件日誌來檢視哪些方法最需要它,並在後續的啟動中主動地 jitting 它們。我們儘可能快地在所有處理器核心上執行此操作。
.NET 6 的 JIT 效率因此得到了極大的提升,對啟動時間產生了很大的影響:
在一些機器 SKU 上,啟動時間提高了近40%!難以置信!
.NET 7
.NET 6 釋出後,我們就立即集中精力升級到 .NET 7。有兩個主要變化需要特別注意:
1.執行緒池的操作方式。
2.一個新的基於區域的 GC。
詳細的測試表明,新的執行緒池設計為我們帶來了更好的效能,所以這裡不用擔心。
事實上,新的垃圾收集器設計在幾個月的時間裡由 .NET 開發者在我們的一些測試機器上進行了具體且廣泛的測試,以確保它沒有引入任何迴歸。在一個對執行時如何工作的假設進行了高度最佳化的系統中,當執行時的一個基本部分極大地改變了其實現時,總數令人擔憂。
幸運的是,在測試中我們發現程式花在 GC 上的時間平均提高了24%,雖然一開始並不是很多。在實際生產中,這個比例甚至更高,接近30%。
解決了這兩個問題後,我們通常會看到大約10-17%的效率提升,這取決於資料中心和工作負載型別。
很大一部分效能提升來自執行時 CPU 使用率的提升,也就是在 Bing 中查詢時 CPU 使用率的降低:
注意:上圖中的值並不代表查詢延遲,它是所有並行路徑上的 CPU 使用率的總和。
在 GC 改進、新的執行緒池和對處理器更有效地使用之間,我們實現了 P95 延遲3-7%的改進,在更高的百分比上改進更多。這種效率的提升讓我們能夠給使用者更快的服務體驗,或者在某些情況下,減少資源使用並以不同的方式實現執行時收益。“效率”對於科技公司來說就像2023年的年度詞彙,.NET 7在我們的努力中扮演了很關鍵的角色。
.NET 8
. NET 8 已經發布了預覽版。我們將開始在這個新的執行時下測試工作流引擎。到目前為止,年復一年地升級到最新版本已經被證明是顯著提高效能的最經濟有效的方法。我們從未期望“免費”獲得所有這些效能優勢,我們一直追求的是平價。很難想象效率方面比較大的改進會永久持續下去(儘管目前還沒有停止的跡象)。我們很高興能站在 .NET 進步的風口浪尖上!