如何确定巨型c#数据集的内存使用情况

时间:2014-02-06 18:44:32

标签: c# .net memory bigdata ram

我在c#windows服务中有一个巨大的数据集,它使用大约12GB的内存。

Dictionary<DateTime,List<List<Item>>>

添加了不断的新数据流,每小时约1GB。旧数据偶尔会被删除。这是一个用于网页的高速缓冲区。

我在配置文件中有一个名为“MaxSizeMB”的参数。我想允许用户输入,比如“11000”,我的应用程序将在每次应用超过11GB的ram使用时删除一些旧数据。

事实证明这令人沮丧。

你会认为你可以调用GC.GetTotalMemory(false)。这将为您提供.net托管对象的内存使用(假设它的内容为10.8GB)。然后你只需要为应用程序中分配的所有其他东西添加一个200MB的常量安全网。

这不起作用。实际上,加载的数据越多,GC.GetTotalMemory和任务管理器之间的差异就越大。我甚至尝试计算出一个常数乘数值而不是一个常数加值,但我无法得到一致的结果。到目前为止,我所做的最好的事情是计算数据结构中的项目总数,乘以96,并假设该数字是ram使用情况。这也令人困惑,因为Item对象是一个32byte的结构。这种假装的ram使用也太不稳定了。有时该应用程序将删除11GB的旧数据,但有时会删除8GB ram使用的数据,因为我假装的数字计算错误的11GB。

所以我可以使用这种保守的假ram计算,并且经常不使用我允许使用的所有ram(比如丢失2GB),或者我可以使用GC.GetTotalMemory而且客户会觉得应用程序结束了偶尔设置ram。

有没有办法在不超出限制的情况下尽可能多地使用ram,因为它出现在任务管理器中?我不在乎数学是乘数,不变增值,功率等等。我希望在达到最大设置时将数据填充到数据结构中并删除数据。

注意:我已经做了一些内存缩小技术,例如使用struct作为Item,list.Capacity = list.Count和GC.Collect(GC.MaxGeneration)。这些似乎是一个单独的问题。

3 个答案:

答案 0 :(得分:2)

使用System.Diagnostics.PerformanceCounter并监控您当前的进程内存使用情况和可用内存,根据此情况,您的应用程序应决定是否删除某些内容。

答案 1 :(得分:2)

答案非常简单。

var n0 = System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64;
var n1 = System.Diagnostics.Process.GetCurrentProcess().WorkingSet64;
var n2 = System.Diagnostics.Process.GetCurrentProcess().VirtualMemorySize64;
float f0 = ((float)n0)/(1000*1000);
float f1 = ((float)n1)/(1000*1000);
float f2 = ((float)n2)/(1000*1000);
Console.WriteLine("private = " + f0 + " MB");
Console.WriteLine("working = " + f1 + " MB");
Console.WriteLine("virtual = " + f2 + " MB");

结果:

private = 931.9096 MB
working = 722.0756 MB
virtual = 1767.146 MB

所有这些关于任务管理器和.net对象大小的呻吟和烦恼以及答案是在一行代码中构建到.NET中的。

我给了Sarvesh一个答案,因为他让我使用PerformanceCounter开始了正确的道路,但GetCurrentProcess()结果是一个很好的捷径来简单地检查你自己的过程。

答案 2 :(得分:1)

几个问题
垃圾收集
获得良好的记忆力量 什么是最大值

您认为存在最大硬度。 但是一个对象需要连续的内存,因此它是一个软的最大值。

对于准确的尺寸测量,您可以记录每个列表的大小并保持运行总计 然后,当您清除读取大小并从该运行总计中减少时。

为什么要对抗.NET内存限制和物理内存限制 我会选择SSD上的数据库 如果它是只读的并且您已知类,则可以像RavenDB一样使用 重新考虑你的设计

好的,所以我对管理.NET内存限制没有太大的帮助,你永远不会驯服。 仍在重新考虑你的设计。
如果您的PK是一个DateTime并且假设您每小时只需要24小时,那么这只是一个对象 在23小时结束时新的先前 - 让GC收集整个事情。