VB.NET 词典的内存大小?

VB.NET Memory Size of Dictionary?

我有一个 class:

Class Test

    Friend myDict As Dictionary(Of Byte, Byte) = New Dictionary(Of Byte, Byte)

    Friend Test1 As Boolean
    Friend Test2 As Boolean
    Friend Test3 As Boolean
    Friend Test4 As Boolean

    Friend Test5 As Byte
    Friend Test6 As Byte

    Friend Test7 As Byte

    Friend Test8 As Boolean

   Public Sub New(smt As String)

    Test1 = True
    Test2 = True
    Test3 = True
    Test4 = True

    Test5 = 51
    Test6 = 58
    Test7 = 0

    Test8 = True

   ' ADDING 64 DICTIONARY ENTRIES HERE

    myDict.Add(11, 0)
    myDict.Add(21, 0)
    myDict.Add(31, 0)
    myDict.Add(41, 0)
    myDict.Add(51, 0)
    myDict.Add(61, 0)
    myDict.Add(71, 0)
    myDict.Add(81, 0)

    myDict.Add(12, 0)
    myDict.Add(22, 0)
    myDict.Add(32, 0)
    myDict.Add(42, 0)
    myDict.Add(52, 0)
    myDict.Add(62, 0)
    myDict.Add(72, 0)
    myDict.Add(82, 0)

    myDict.Add(13, Nothing)
    myDict.Add(23, Nothing)
    myDict.Add(33, Nothing)
    myDict.Add(43, Nothing)
    myDict.Add(53, Nothing)
    myDict.Add(63, Nothing)
    myDict.Add(73, Nothing)
    myDict.Add(83, Nothing)

    myDict.Add(14, Nothing)
    myDict.Add(24, Nothing)
    myDict.Add(34, Nothing)
    myDict.Add(44, Nothing)
    myDict.Add(54, Nothing)
    myDict.Add(64, Nothing)
    myDict.Add(74, Nothing)
    myDict.Add(84, Nothing)

    myDict.Add(15, Nothing)
    myDict.Add(25, Nothing)
    myDict.Add(35, Nothing)
    myDict.Add(45, Nothing)
    myDict.Add(55, Nothing)
    myDict.Add(65, Nothing)
    myDict.Add(75, Nothing)
    myDict.Add(85, Nothing)

    myDict.Add(16, Nothing)
    myDict.Add(26, Nothing)
    myDict.Add(36, Nothing)
    myDict.Add(46, Nothing)
    myDict.Add(56, Nothing)
    myDict.Add(66, Nothing)
    myDict.Add(76, Nothing)
    myDict.Add(86, Nothing)

    myDict.Add(17, 0)
    myDict.Add(27, 0)
    myDict.Add(37, 0)
    myDict.Add(47, 0)
    myDict.Add(57, 0)
    myDict.Add(67, 0)
    myDict.Add(77, 0)
    myDict.Add(87, 0)

    myDict.Add(18, 0)
    myDict.Add(28, 0)
    myDict.Add(38, 0)
    myDict.Add(48, 0)
    myDict.Add(58, 0)
    myDict.Add(68, 0)
    myDict.Add(78, 0)
    myDict.Add(88, 0)

    Console.WriteLine("Created New!")

End Sub

Public Sub New()

End Sub

End Class

当我使用这个 class 克隆 1.000.000 个时:

Public Clones As List(Of Test) = New List(Of Test)

Public Sub BenchmarkTest(cnt As Long)

    Clones.Clear()
    GC.Collect()

    Dim t As Long = Now.Ticks
    Dim tst As Test = New Test("")

    For x As Long = 1 To cnt
        Clones.Add(DeepCopy(tst))
    Next

    Console.WriteLine("Copied " + Clones .Count.ToString + " in " + ((Now.Ticks - t) / 10000).ToString + "ms (" + ((Now.Ticks - t) / 10000000).ToString + " secs)")

End Sub

Public Function DeepCopy(inputTest As Test) As Test

    Dim other As Test = New Test()
    other.Test1 = inputTest.Test1
    other.Test2 = inputTest.Test2 
    other.Test3 = inputTest.Test3 
    other.Test4 = inputTest.Test4 
    other.Test5 = inputTest.Test5 
    other.Test6 = inputTest.Test6 
    other.myDict = New Dictionary(Of Byte, Byte)(inputTest.myDict)
    Return other

End Function

然后我打开任务管理器查看我的应用程序使用了多少内存,我看到它使用了 1,300+Mb

嗯,根据我的计算,我的 class 大小只能是 136 字节。 (64 个字典条目(字节,字节)= 128 字节 + 8 字节(对于 test1 到 test8)= 136 字节)

将它乘以 100 万应该是 130Mbytes,而不是 1300。

我的计算有什么问题?为什么它使用了将近 10 倍的内存?

您过度简化了计算。 .NET 对象带有必要的开销,不能简单地扁平化为逐字节等效。 (你的计算让我想起了 C 风格的结构对齐。)

测试 class 中主要的 "grabber" 记忆将是词典。如果你一步一步地分析你的过程,你会发现简单地实例化一个空字典会消耗内存。当您开始添加项目时,事情会变得更加有趣。 .NET 集合不会在您添加项目时以线性方式增长,那样效率太低了。集合将通过一些内部定义的方案(有时是斐波那契数列,有时是当前容量的简单加倍)增长,其中添加足够的项目将假设将添加另一个项目块并保留该内存。

我知道这都是理论性的、抽象的、高层次的讨论,不会给出具体的答案,但我的意思是要传达这个问题非常复杂,准确计算内存利用率可能非常困难。

这里有一个不错的 Code Project article 提到了字典中的一些性能和内存使用问题。

这里是another interesting link from Simple-Talk。评论部分包含有关 .NET 集合增长策略的有趣讨论。享受吧。

C# 中的快速示例。 (这很脏,不要带它去银行,但证明了这一点。See GC.GetTotalMemory

Console.WriteLine("Bar is doing stuff.");
Console.WriteLine(GC.GetTotalMemory(true));
var dict = new Dictionary<byte, byte>();
Console.WriteLine(GC.GetTotalMemory(true));
dict.Add(8, 9);
Console.WriteLine(GC.GetTotalMemory(true));

输出:

53,328
53,980
54,052

请注意,一个空的 byte/byte 字典占用 652 个字节。添加 byte/byte 的单个条目会使字典大小增加 72 个字节...您没有看到的一件事是每个条目实际上在内部由 DictionaryEntry class.[=15 的实例表示=]