服務測試碰釘子Server GC

smark發表於2018-11-03

如果發現你的dotnet core服務併發上不去,但cpu資源還比較充足那就要注意了!因為這很有可能是你沒有設定一個執行項導致...,下面要提到的就是GC.Server這玩意,實際上專案編譯中並沒有這一項設定,通過app.config設定也無效。那到底這是一個什麼東西接下來說一下實際的應用效果和配置方式。

原因

最近一直做在做FastHttpApi方面的效能測試,在本機測試效能一直都比較良好;問題部署上伺服器後效率竟然跑不過asp.net core webapi,這結果和在本地測完全是兩碼事;主要原因是12核的CPU無法跑到超過8核的資源,而asp.net core基本能跑滿!為了找到原因還把'Kestrel.Transport.Sockets'程式碼看了一遍,怎看也不看不出有本質上的效能優勢,不過實測結果告訴我的確是這樣了;於是又仔細翻閱了程式碼和配置檔案也沒看到有什麼特別的配置和執行緒配置資訊,後來實在沒辦法了又看了一遍釋出後的配置資訊,結果看了一個System.GC.Server的配置資訊。

關於Server GC的解釋

網上對System.GC.Server有實質性介紹的文件並不太多,MSDN翻譯如下: 公共語言執行時 (CLR) 支援兩種型別的垃圾回收:工作站垃圾回收(適用於所有系統)和伺服器垃圾回收(適用於多處理器系統)。 使用 <gcServer> 元素以控制 CLR 執行的垃圾回收型別。 使用 GCSettings.IsServerGC 屬性以確定是否啟用伺服器垃圾回收。 對於單處理器計算機,預設的工作站垃圾回收應該是最快捷的選項。 對於雙處理器計算機,最快捷的選項既可以是工作站垃圾回收又可以是伺服器垃圾回收。 對於兩個以上處理器的計算機,伺服器垃圾回收應該是最快捷的選項。

從MSDN上並沒有太多講述Server GC把發揮的作用,最明確一點就是可以使用多處理器對GC進行快捷處理,至於這種配置在服務程式中具體能發揮多少作用呢沒有一個具體的指標性東西。然而以於asp.net mvc這些專案預設都會編譯成ServerGC模式並不需要配置,而我們自己寫的Console程式則不是,需要根據情況自行配置。

修改後的執行效果

於是把這配置資訊複製到測試程式上,結果一跑整體的效果才出來,這個時候服務基本可以跑滿所有核資源;RPS從原來的最大14萬提高到24萬,在壓測1000萬請求的過程保持穩定。由於對GC瞭解不是很深入,初步猜想由於預設是單執行緒處理GC,這樣會導致所有執行緒都會卡在GC處理上;即使你加大執行緒池數量或加大併發也不會從根據上解決問題,只會讓併發處理延時加大! 當在多核開啟GC Server的情況上GC就不會卡在一個執行緒上由多核的執行緒來完成,由於GC處理不會卡在一個執行緒,所以資源能夠完全發揮出來提高併發處理能力。

程式配置Server GC

專案屬性配置裡是沒有Server GC這項設定,網上有資料說在app.config中進行配置,但這個配置對dotnet core程式是無效的。後來在MSDN找到資料需要手動編輯csproj 檔案在PropertyGroup中新增相關內容.

<PropertyGroup>
  <ServerGarbageCollection>true</ServerGarbageCollection>
</PropertyGroup>

相關文章