[C#] Large Object Heap

LOH(Large Object Heap) GC .NET 具有 GC(garbage collector),使開發員不需要過多考慮記憶體控管,因為 GC 會自動移除「死掉的」物件,並將記憶體重排。 這些小的物件會透過釋放死的物件,並移動集合中存活的物件,以確保沒有間隙。(事實上並非原地移動,而是將之全部複製到新的記憶體區塊,這樣可以簡化分配記憶體的過程,這樣意味著,空間都會出現在區塊的尾端,所以不需要進行掃描來找尋記憶體區塊來儲存新的物件。 LOH LOH(Large Object Heap) 指的是大型物件堆,也就是大小超過 85000 bytes 的物件,GC 會將之視為獨立的部分,GC 會優先處理其它的堆,原因是若要透過複製移動的方法來重新分配 LOH,它們需要兩倍的記憶體來進行,會使得 GC 花費大量的時間進行任務。 取而代之,GC 不會移動 LOH,而是將之留在原地,使得空間變得碎片化(fragmented)。當移除 LOH 時,會將空間原地保留,當要放入新的物件時,若區塊的尾端沒有足夠的空間,則會在這些 LOH 之間的空洞找尋可用空間,在沒有足夠空間時,擴展堆。 隨著時間堆移,即使不會發生 memory leakage,由於 LOH 之間的碎片空間會愈來愈小,不足以放置新的物件。在最糟的狀況下,這些碎片空間佔有的空間很大,但又不足以放置新的物件,且碎片的個數很多,這可能就會導致更多的產生 OutOfMemoryException。 如何解決 防止或減少使用大型物件的需求。 定期停止或重啟受影響的應用程式。 將大型物件重構成不同的數據結構,如 100000 個元素的數組,儲存成 10 個 10000 個元素的數組。 System.Collections 中也有一個 Capacity 的屬性來促進這種設計模式來避免大型物件的產生,有效的共享大型數據結構也有助於減少大型物件。 Reference: Andrew Hunter - The Dangers of the Large Object Heap Reference: Microsoft - The large object heap on Windows systems

<span title='2023-07-22 20:59:57 +0800 +0800'>July 22, 2023</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;Rain Hu

[CS] Sample cost for performance test

Sample code for stop watch using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Runtime.CompilerServices; using System.Data.Common; using System.Diagnostics; using System.Drawing; using System.Text; using System.Threading.Tasks; namespace Rainspace.PlayGround { public class Program { public static void Main(string[] args) { Stopwatch sw = new Stopwatch(); sw.Start(); System.Console.WriteLine("==============Accumulate1=============="); System.Console.WriteLine("Result: " + Accumulate(0, 100, 0)); sw.Stop(); System.Console.WriteLine("Time cost: " + (sw.ElapsedTicks/1.0e6).ToString() + "ms"); sw.Reset(); sw.Start(); System.Console.WriteLine("==============Accumulate2=============="); System.Console.WriteLine("Result: " + Accumulate(0, 100, 0)); sw.Stop(); System.Console.WriteLine("Time cost: " + (sw....

<span title='2023-05-16 21:26:24 +0800 +0800'>May 16, 2023</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;Rain Hu

[C#] C#3、LINQ 及相關特性

1. 屬性的自動實現 在 C#3 以前,每個屬性需要手動實現,也就是需要手動為屬性添加 get 訪問器與 set 訪問器,如: private string name; public string Name { get { return name; } set { name = value; } } 在 C#3 以後,可以透過自動實現的方式撰寫: 其中命名為 name 的變數由編譯器自動創建並為其賦予名稱。 public string Name { get; set; } 但在 C#3 時,不能宣告 readonly 的自動屬性,且不能在宣告時賦予初始值,在 C#6 做了修正。在 C#3 只能透過訪問子分離來模擬 readonly: public string Name { get; private set; } 2. 隱式類型(var) 靜態類型 vs. 動態類型: 靜態類型是面向編譯的的語言,故所有類型由編譯器決定,在編譯期就會完成綁定。 動態類型則是延遲綁定的時間,在執行期才進行類型綁定。 顯式類型 vs. 隱式類型: 顯式類型代表在程式碼表達式便給出具體的類型訊息。 隱式類型則允許了類型推斷,透過上下文判斷出類型. C#3 開始支援隱式類型的寫法,關鍵字是 var。...

<span title='2023-05-01 14:10:48 +0800 +0800'>May 1, 2023</span>&nbsp;·&nbsp;4 min&nbsp;·&nbsp;Rain Hu

[C#] Namespace Alias 命名空間別名

1. 命名空間別名 命名空間(namespace)的作用是允許在不同的命名空間下定義多個同名 class。 使用命名空間別名(namespace alias)可以避免為了保證命名唯一而使用命名空間而導致的命名過度冗長。 using System; using WinForms = System.Windows.Forms; using WebForms = System.Web.UI.WebControls; class Program { public static void Main() { Console.WriteLine(typeof(WinForms.Button)); Console.WriteLine(typeof(WebForms.Button)); } } 2. 命名空間別名限定字符 上例的程式碼存在一個潛在的問題,如果程式中同時引用了一個同名類別,如 class WinForms,那麼 WinForms.Button 就會被判斷成該類別的 Button 成員。 為了避免上面的情形發生,在 C#2 引入了命名空間別名限定字符(::),使用 :: 代表前面接的一定是命名空間。 public static void Main() { Console.WriteLine(typeof(WinForms::Button)); Console.WriteLine(typeof(WebForms::Button)); } 3. 全局命名空間別名 C#2 引入的全局命名空間別名,可以指示全局命名空間中的類別,也可以用於類別完全限定名的一個「根」命名空間。 global using global::System.DateTime; 4. 外部別名 假設有不同的程式提供了相同的命名空間,而命名空間又有相同的 class 名稱,則需要外部別名(extern)來處理。 extern alias JsonNet; extern alias JsonNetAlternative; using JsonNet::Newtonsoft.Json.Linq; using AltJObject = JsonNetAlternative::Newtonsoft....

<span title='2023-02-28 22:51:08 +0800 +0800'>February 28, 2023</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;Rain Hu

[C#] Property getter/setter access separate 訪問權限分離

1. getter/setter 的訪問權限分離 在 C#1 中,getter 跟 setter 共用一個 access modifier,意思是 getter 與 setter 擁有同樣的訪問權限,這個顯然是不合理的。 private string text; public string Text { get { return text; } set { text = value; } } 更常見的情境應該是 setter 的訪問權限比 getter 的訪問權限更小,這在 C#2 中可以透過下面例子的方式來達到: private string text; public string Text { get { return text; } private set { text = value; } }

<span title='2023-02-28 22:18:25 +0800 +0800'>February 28, 2023</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;Rain Hu