VB.NET字典的内存大小?

时间:2015-03-13 03:51:37

标签: .net vb.net performance memory dictionary

我有一个班级:

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

当我使用以下方法克隆此类的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

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

将它与100万相乘应该是大约130M字节,而不是1300字节。

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

1 个答案:

答案 0 :(得分:3)

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

Test类中内存的主要“抓取器”将是Dictionary。如果您逐步分析您的过程,您将看到简单地实例化一个空字典将消耗内存。当你开始添加项目时,事情变得更有趣。当您添加项目时,.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

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