簡體   English   中英

.NET自定義結構類型的內存開銷是多少?

[英]What is the memory overhead of a .NET custom struct type?

有一個與.NET對象相關的固定開銷,在這個SO問題中有更全面的概述: .NET對象的內存開銷是12或24字節,具體取決於你是在32位還是64位進程。

也就是說,像int, double, boolean等基本值類型不會產生任何開銷,因為它們是值類型

在您的應用程序中放置自定義struct類型的位置在哪里? 一方面,它們是值類型,如上面的int, double, boolean [所以不應該產生開銷]但另一方面它們間接地從System.Object派生,因此(技術上)應該產生開銷。

在您的應用程序中放置自定義結構類型的位置在哪里?

它們與原始類型沒有什么不同。 除了他們擁有的領域之外,它們不會帶來額外的開銷。 它們從object派生的事實並不意味着它們會產生引用類型攜帶的開銷,即方法表指針和同步根塊。

你可以使用Marshal.SizeOf來測試它:

void Main()
{
    var f = new Foo();
    Console.WriteLine(Marshal.SizeOf(f));
}

public struct Foo
{
    public int X { get; set; }
    public int Y { get; set; }
}

這將以32位模式打印8,這正好是兩個整數值(每個4個字節)。

注意Marshal.SizeOf將輸出非托管對象的大小。 CLR仍然可以自由地重新排序字段或將它們打包在一起。

結構的大小由其字段大小的總和加上正確對齊的字段之間的填充,加上結構末尾的填充,確保在結構存儲時它們仍然正確對齊數組。

因此,對於一個,結構並不完全不可能包含引用類型的字段。 像一個字符串。 在這種情況下,結構將變得更大,因為引用是引擎蓋下的指針,占用8個字節而不是4個字節。

襯墊是更加狡猾的細節。 在32位模式下,變量不能指向優於4的對齊。 doublelong ,8字節類型的問題很容易被錯誤對齊。 特別是影響32位程序的性能,如果雙重在L1高速緩存邊界線上未對齊,則讀取或寫入速度可能是3倍。 這也是C#內存模型中這些類型不是原子的核心原因。 在64位模式下不是問題,然后CLR必須並確實提供8的對齊保證。

然而,CLR確實試圖在32位模式下給這樣的結構成員正確對齊,即使結構本身不能保證對齊。 否則,結構的副作用具有隱式[StructLayout(LayoutKind.Sequential, Pack=8)]屬性。 CLR源代碼中的一個奇怪的是,執行此操作的C ++語句沒有注釋。 我懷疑它是一個快速修復不到恆星非托管互操作性能 ,保持結構blittable對速度非常重要。

然而,如果結構包含一個本身就是沒有順序布局的結構的成員,那么CLR就會放棄。 值得注意的是,這發生在DateTimeDateTimeOffset ,編寫它們的程序員在其上應用[StructLayout(LayoutKind.Auto)]屬性是出於非常神秘的原因。 在DateTimeOffset的情況下可能是復制/粘貼錯誤。 結構的布局現在將是不可預測的,它也變為LayoutKind.Auto,CLR重新排列字段以最小化結構大小。 可能會導致x64模式下的額外填充。

這些是不應該擔心的模糊實現細節。

字段的對齊可能會有一些開銷:

https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.structlayoutattribute(v=vs.100).aspx

例如

  public struct Test {
    public Byte A;
    public long B;
  }

將大小在64位處理16個字節和12個字節在32位過程相應地(當我們可以預期只有9個字節);

零。

除非由於對齊而存在間隙,否則這就是這些差距的成本。

但是否則結構就像字段是在堆棧上布局的單獨變量一樣。

雖然它是盒子,你通過object處理它,它具有與任何其他引用類型相同的開銷。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM