在基於“less rope to hang yourself with”思想下,.NET 框架沒有給開發提供很多太多的配置選項。但在大多數情況下,GC會跟你的硬體配置,及可用資源以及程式自己的行為做調整。當然也提供一些高級的配置使用,但這取決於你程式的類型。 ...
配置選項
在基於“less rope to hang yourself with”思想下,.NET 框架沒有給開發提供很多太多的配置選項。但在大多數情況下,GC會跟你的硬體配置,及可用資源以及程式自己的行為做調整。當然也提供一些高級的配置使用,但這取決於你程式的類型。
工作站與伺服器
你首要的是為應用選擇是在工作站還是伺服器模式下運行。
系統預設為工作站模式。在這種模式下,GC在觸發回收時,回收線程與當前主線程的優先順序一樣。對於簡單的應用程式,特別是存在工作站里有多個托管進程需要做交互的情況下,以及單處理器的電腦上,這可能是唯一的選擇,你試圖修改任何配置對運行不會產生任何影響。
伺服器模式則會給每個業務邏輯進程創建一個專用的線程。這個線程會運行在高優先順序(THREAD_PRIORITY_HIGHEST),但平時這個線程會處於休眠狀態,一旦需要做GC就會被喚醒。完成GC後又會進入休眠。
此外,CLR還會為每個處理器分配一個單獨的堆。每個處理器堆里,包含一個小對象堆和大對象堆。從你的應用程式角度上看,你的代碼不知道引用的對象是屬於哪個堆上面的(他們都有相同的虛擬地址空間)。
使用多個堆有下一些優點
- 垃圾回收可以並行處理。每個GC線程處理一個對應的堆。這是的伺服器模式的GC比工作站模式要快的原因。
- 某些情況下,分配速度會更快,尤其是將大對象相對分配在同一個堆上快。還有一些其他內部差異,比如記憶體段的大小,越大的段在做垃圾回收時時間也會越長。
你可以在App.config 文件里的
<configuration>
<runtime>
<gcServer enabled="true"/>
</runtime>
</configuration>
你要如何選擇工作站或者伺服器模式嗎?
如果一個多處理器機器上只運行你的應用程式,那麼最明智的選擇是:伺服器模式。它在大多數情況下可以降低GC的延遲。
另一位方面,如果你的機器有多個托管進程的應用程式,則需要具體分析了。如果這幾個托管應用都採用伺服器模式,那麼會創建很多個高優先順序的線程,這個會對線程調度產生衝突和影響。在這種情況下,最好使用工作站模式。
如果你真的想在同一個台機器里的多個應用程式開啟伺服器GC模式,還有另外一種選擇,就是為應用程式綁定特定的CPU。
無論你選擇哪種模式,本書的大部分技巧都使用這兩種模式。
後臺GC
修改後臺GC配置會更改2代對象的回收策略。相對於0代和1代的回收的前臺GC,它不會中斷當前應用里其他的線程執行。
後臺GC在會而外創建一個線程用來處理2代對象的回收。這意味著,如果你同時開啟後臺GC和伺服器GC,你將為每個處理器創建2個線程來處理GC。但這沒啥大不了的,雖然進程里多了很多個線程,但這些線程在大部分時間里還是不工作的。
在你的應用執行的時候GC也可以同時進行,但在某些情況下,還是會發生阻塞。在這時,後臺GC還是會將應用程式里的其它線程給掛起。
如果使用工作站模式,則始終開啟後臺GC模式,從.NET4.5開始,預設情況下伺服器GC模式下也會開啟,當然你也可以關閉它。
以下是關閉後臺GC的配置
<configuration>
<runtime>
<gcConcurrent enabled="false"/>
</runtime>
</configuration>
實際上,我們很少有理由去禁用後臺GC。如果你想通過禁用後臺GC的線程來提高你的應用程式在CPU的占用率,但這個想法是不現實的。但如果是減少GC的延遲或者頻率可以考慮關閉它。
低延遲模式
如果你的應用希望在一段特定時間里高速執行,不希望被GC的2代回收打擾。你可以通過改變 GCSettings.LatencyMode 的設置來實現。
LowLatency—只能在工作站模式運行,它可以暫停2代回收。
SustainedLowLatency—可以在工作站和伺服器模式下執行。它可以暫停完整的2代回收,但如果你開啟里後臺GC模式,你還是可以在後臺GC線程里對2代對象做回收。
這兩種模式都將大大的增加記憶體的消耗,因為它沒對記憶體做壓縮。如果你的應用需要消耗大量的記憶體,則最好避免開啟這兩個模式。
當你要準備進入低延遲模式前,最好手動執行一次完整的GC(GC.Collect(2, GCCollectionMode.Forced)。等離開低延遲模式後,也手動觸發一次完成GC。
預設情況下,是不需要開啟這個模式。只有你的程式執行時間不要被GC打擾才需要開啟,不用在全過程都開啟。舉個慄子:如果你有一個股票交易的高頻應用,在交易時間段里不希望發生GC回收暫停應用執行。但在股市交易結束後,你可以關閉這個模式進行完整的GC回收直到股市重新開市。
如果要開啟低延遲模式,至少要符合以下標準:
- 在正常執行期間,完整的垃圾回收操作是不可接受的
- 應用程式消耗的記憶體要遠小於可分配記憶體
- 應用程式在開啟低延遲模式後,要有足夠的記憶體撐到下一次手動執行完整回收或者重啟。
這是一個很少用的配置,如果你要使用請三思而後行,因為開啟之後會出現一些意想不到的後果。如果你認為還是有必要使用,請確保你的應用經過了充分測試。在開啟後,系統會產生更頻繁的0代和1代的回收操作,用來減少完整的回收,這可能會導致一些其他性能問題。這可能會導致解決了一個又另外產生了一個問題。
最後,請註意,低延遲模式不是一個保證。如果GC在做回收的時候仍然拋出了OutOfMemoryException異常,仍然有可能會不管你的配置選項,進行一次完整的GC回收。