為什麼聽說過 JVM 調優,卻沒聽說過 CLR 調優?


因為題主您就是沒聽說過 &>_&<||||

假定題主說的是下面三個層面的調優的頭兩種情況:

  1. 對VM的配置參數調優(例如GC參數)
  2. 對應用程序自身的代碼調優
  3. 對VM自身的實現調優

(2)的話無論什麼語言什麼環境都好,追求性能的人肯定都有在做。Java和.NET都有好用的profiler可以幫助這方面的調查和調優。

有時候參數調優還不夠的地方,也只能自己改自己的應用代碼來解決問題了。請看一個經典案例:In managed code we trust, our recent battles with the .NET Garbage Collector

(3)的話,CLR還沒開源的時候,也無從調起。倒是有不少人給Mono貢獻改進性能的patch,也算是廣義上「.NET」的VM實現層面調優吧。

在CoreCLR開源後,也有不少人給CoreCLR貢獻各種patch呢,包括「調優」。

.NET碼農們以前時不時會中招的一種地方是程序進入GC的耗時(time-to-GC),也就是從CLR說「我要開始做GC了」到「真正開始做GC」之間的耗時。這裡主要開銷來自請求所有應用線程暫停(SuspendEE),這些線程要多久才完成對該請求的響應。聽說過這個過程中會發生「250ms的倍數的等待時間」不?請跳傳送門:Garbage Collection Thread Suspension Delay (250ms Multiples)

像這種問題就是不進到VM內部做修改的話無法解決的。

(1)的話,其實就算當年CLR還沒開源的時候,CLR也是有調優參數可以配置的呢。

最經典的就是選擇試用Workstation GC(WKS GC)或者Server GC(SVR GC)。見過&參數不?

後來可以配置使用Concurrent GC、Background Workstation GC、Background Server GC等。

用戶還可以在代碼里通過 GCSettings.LatencyMode 屬性來影響GC的行為。

看,調優參數列表之一:Runtime Settings Schema

不過CLR跟HotSpot VM在配置上有一個顯著的區別,就是CLR不需要用戶指定一個「GC堆的最大大小」。這跟CLR的GC堆的基礎設計思路有關係。

HotSpot VM的GC堆一定要使用連續的虛擬地址空間。VM在啟動的時候會一口氣reserve GC所需要的整個地址空間,然後再按需commit。-Xmx會參與到GC堆最大大小的計算中。

CLR的GC堆則是分段式的(segemented),GC堆所用的空間會一個個segment分配,用滿了一個再去分配一個新的;segment不需要在連續的地址空間上。這樣GC堆可以按需自動增長或者縮減,可以一直增長到耗盡虛擬地址空間或者達到配額。

CLR這種分段式GC堆的好處是,在Windows上,特別是32位Windows上,虛擬地址空間中用戶程序可以用的部分是比較零碎的,想要用到盡就不能對「連續的地址空間」有太多要求,這種條件下CLR跑在Windows上就可以充分利用資源。

而且這樣一來,用戶就不用頭疼實現想好要配置多大的堆給CLR用了。反正它需要用多少會自己去增長。這用戶體驗就比絞盡腦汁想個好-Xmx要爽。

這種做法的壞處…怎能沒有壞處呢。壞處也有若干。其中一個就是在這樣的堆上實現的分代式GC的write barrier效率會比HotSpot那種用連續地址空間的要差一些。而且segmented heap實現起來也稍微複雜一些。


當年 CLR 的官版你又改不了


可能是之前CLR沒用開源代碼,也沒那麼多參數可調。但是可以根據CLR對源代碼(C#)調優啊,比如這本書 Optimize Your C# Applications 就不錯。


不僅改不了,剛出4.0時,我記得有一個階段,從3.5到4.0連調試都做不到。

京東當時那個項目好像就死在這個階段,默哀。

所以,大項目,還是開源好。bug多沒事,就怕有bug調不了、改不了。


一個是改不了,另一個是沒人會


推薦閱讀:

WebApi和MVC有什麼區別?
ASP.NET開源以後會有更多的網站選擇這個平台么?
ADO.NET的SqlParameter(String,?Object)的構造函數第二個參數不能為0?
處理XMLHttpRequest時如何判斷是否是自己網站發出的?
.net怎麼實現自己的非同步方法?

TAG:NET | Java虛擬機JVM | C# | CLR |