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 的实例表示=]
我有一个 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 的实例表示=]