我正在使用C#和.NET Framework 4.6.2以及Entity Framework 6.1.3开发Windows服务。
我在该服务上有一个Web API接口,在一个Controller的方法中,我创建了一个包含超过一百万个字符串的字典:
Dictionary<string, List<string>> codes;
此词典在另一个方法中创建:
codes = GetCodesAsDictionary(connectionString, productionId);
我将此变量传递给静态类中的静态方法。
一个Visual Studio 2015的内存分析器我看到当我调用此方法时内存增长到1,1Gb,但是当方法结束时,内存保持为1,1Gb。
如果我再次调用该方法,则内存再次增长到2Gb,并且在方法完成后,内存再次变为1,1Gb。
我试图将codes
变量作为参考传递,但我获得了相同的内存分配。我必须停止服务并重新运行它以释放1,1Gb。顺便说一句,我通过引用传递它,因为我不希望静态方法复制它。
你知道为什么在方法结束后它没有释放这么多的内存吗?
更新
我用实例类更改了静态类(从静态类复制方法),我得到了相同的结果(分配了1,1Gb内存)。
第二次更新:
我还改变了字典的创建方式:
Dictionary<string, List<string>> codes = null;
GetCodesAsDictionary(connectionString, productionId, out codes);
我得到了相同的结果:分配了1,1Gb内存。
第三次更新:
我用Dictionary
更改了KeyValuePair<byte, string[]>[]
,我得到了相同的结果,分配了1,1Gb。现在,我没有使用string
作为键,而是使用byte。
答案 0 :(得分:0)
你知道为什么在方法结束后它没有释放这么多的内存吗?
如果还没有任何参考文献,那可能就是垃圾收集者没有感觉到释放内存的冲动,即使它已经不再使用了
您可以尝试force garbage collection并查看是否释放了内存。如果没有,您的代码可能存在问题。
(旁注:如果你在字符串中有大量的重复,你可能会因为实习而受益。它会大大减少内存压力。但是这样可以随时分配这些字符串。)
答案 1 :(得分:0)
您确定在该方法中创建并使用 字典吗?
如果没有其他帮助,您可以尝试使用GC.Collect()
,但这应该仅用作最后的手段。
https://msdn.microsoft.com/en-us/library/system.gc.collect(v=vs.110).aspx
编辑:您可以尝试使用GC.AddMemoryPressure
方法而不是我之前建议的方法。您需要传递内存量以使GC意识到可以收集一些内存这一事实。
https://msdn.microsoft.com/en-us/library/system.gc.addmemorypressure(v=vs.110).aspx
尝试以下方法适用于您:
Dictionary<string, List<string>> codes = new Dictionary<string, List<string>>();
long bytesBefore = GC.GetTotalMemory(true);
// Code that adds items to your dictionary comes here
long bytesAfter = GC.GetTotalMemory(true);
// After your method ends:
GC.AddMemoryPressure((long) (bytesAfter - bytesBefore));