詳細介紹.NET中的效能改進

來源:互聯網
上載者:User
  .NET 4.6中帶來了一些與效能改進相關的CLR特性,這些特性中有一部分將會自動生效,而另外一些特性,例如SIMD與非同步本機存放區(Async Local Storage)則需要對編寫應用的方式進行某些改動。

  SIMD

  Mono團隊一直以他們對SIMD,即單指令流多資料流特性的支援引以為傲。SIMD是一種CPU指令集,它能夠在同一時間對最多8個值進行同一操作。而隨著.NET CLR版本4.6的推出,Windows開發人員終於也能夠使用這一特性了。

  為了實際觀察一下SIMD的效果,可以參考一下這個樣本。假設你需要通過c[i] = a[i] + b[i]這種形式對兩個數組進行相加,以得到第三個數組。通過使用SIMD,你可以按照以下方式編寫代碼:

for (int i = 0; i < size; i += Vector.Count) {     Vectorv = new Vector(A,i) + new Vector(B,i);     v.CopyTo(C,i); }

  請注意這個迴圈是如何按Vector<int>.Count的取值進行遞增的,根據CPU類型的不同,它的取值可能是4或是8。.NET JIT編譯器將根據CPU的不同產生相應的代碼,以4或8的值對數組進行批量相加。

  這種方式看起來有些繁瑣,因此微軟還提供了一系列輔助類,包括:

  • Matrix3x2 結構

  • Matrix4x4結構

  • Plane結構

  • Quaternion結構

  • Vector 類

  • Vector(T) 結構

  • Vector2結構

  • Vector3結構

  • Vector4結構

  程式集卸載

  恐怕大多數開發人員都不知道這一點:.NET經常會對同一個程式集載入兩次。發生這種情況的條件是.NET首先載入了某個程式集的IL版本,隨後又載入了同一程式集的NGEN版本(即先行編譯版本)。這種方式對於實體記憶體來說是相當嚴重的浪費,尤其是對諸如Visual Studio這樣的大型32位應用程式來說更為明顯。

  而在.NET 4.6中,一旦CLR載入了某個程式集的NGEN版本,它會自動清空對應的IL版本所佔用的記憶體。

  記憶體回收

  早先我們曾討論過.NET 4.0中所引入的記憶體回收延隔時間模式,雖然這種方式比起讓GC完全停止一段時間的做法要可靠許多,但對於許多GC情境來說,這種方式仍算不上完整。

  在.NET 4.6中,你將能夠通過一種更精密的方式臨時中止記憶體回收行程的運作,新的TryStartNoGCRegion方法允許你指定在小對象以及大對象的堆中需要多少記憶體。

  如果出現記憶體不足的情況,運行時將會返回false,或是停止運行,直到通過GC清理得到足夠的記憶體為止。你可以通過為TryStartNoGCRegion傳入某個標記的方式控制這一行為,如果你成功地進入了某個無GC地區(在過程結束前不允許進行GC),那麼在過程結束時必須調用EndNoGCRegion方法。

  在官方文檔中並沒有說明該方法是否是安全執行緒的,不過考慮到GC的工作原理,你應當盡量避免讓兩個進程同時嘗試改變GC狀態的做法。

  對於GC的另一項改進是它處理pinned對象(即一旦分配後不可移動位置的對象)的方式。雖然在文檔中對此方面的描述有些語焉不詳,但當你固定了某個對象的位置時,通常也會固定其相鄰對象的位置。Rich Lander在文中寫道:

GC將以一種更最佳化的方式處理pinned對象,因此GC能夠將pinned對象周圍的記憶體進行更有效地壓縮。對於大量使用pin方式的大規模應用來說,這一改動將極大地改進應用的效能。

  GC對於如何使用較早的幾代中的記憶體方面也體現出更好的智能性,Rich繼續寫道:

第1代對象升級為第2代對象的方式也得到了改進,以更有效地使用記憶體。在為某一代分配新的記憶體空間之前,GC會先嘗試使用可用的空間。同時,在利用可用空間地區建立對象時使用了新的演算法,使新分配的空間大小比起從前更接近於對象的大小。

  非同步本機存放區

  最後一項改進與效能並沒有直接的關係,但通過有效利用仍然能達到最佳化的效果。在非同步API還沒有流行起來的年代,開發人員可以利用執行緒區域儲存(TLS)緩衝資訊。TLS對於某個特定的線程來說就像是一種全域對象,這意味著你可以直接存取上下文資訊並進行緩衝,而無需顯式地傳遞某種內容物件。

  而在async/await模式中,執行緒區域儲存就變得毫無用武之地了。因為每次調用await的時候,都有可能跳轉至另一個線程。而且即便僥倖避開了這種情況,但其它代碼也有可能跳轉到你的線程中並幹擾TLS中的資訊。

  新版本的.NET引入了非同步本機存放區(ALS)機制以解決這一問題,ALS在語義上等價於執行緒區域儲存,但它能夠隨著await的調用進行相應的跳轉。這一功能將通過AsyncLocal泛型類實現,其內部將調用CallContext對象用於儲存資料。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.