管理类的实例数

时间:2013-08-11 17:25:57

标签: c# out-of-memory

我有一个B类,我从中生成大量实例以加速搜索优化问题。这个数字变得如此之大,我经常会产生OutOfMemory-Exceptions。作为解决方法,我每隔x秒减少一次实例数,但我想做一些更明智的事情。为此,我想知道:

  1. 管理“活着”(已创建但尚未收集垃圾)的实例数的好方法是什么

  2. 更多技术性:我如何估算我必须使用(比如说)我的实例大约一半的RAM?

5 个答案:

答案 0 :(得分:5)

首先,我会尝试尽可能减少每个对象的内存占用。由于您创建了大量对象,因此很多对象可能共享相似的属性,这使它们成为flyweight pattern的完美候选对象。根据维基百科文章的一个经典例子是文字处理:

  

flyweight模式的典型示例用法是用于字处理器中字符的图形表示的数据结构。对于文档中的每个字符,可能需要包含字体轮廓,字体度量和其他格式数据的字形对象,但是对于每个字符,这将达到数百或数千个字节。相反,对于每个字符,可能存在对文档中相同字符的每个实例共享的flyweight字形对象的引用;只需要在内部存储每个字符的位置(在文档和/或页面中)。

作为第二步,我会估计单个对象的大小。我在此上下文中强调估算,因为获取实际大小为not that easy in C#。然后,可以使用此估计值来设置可以安全实例化的对象的最大数量N,而不会遇到OutOfMemoryException

您可以通过在每次创建或销毁对象时更新对象计数器来跟踪有多少对象(大约)活着来利用此信息,例如。

class Foo {

    private static NumberOfInstances = 0;

    public Foo() {
        NumberOfInstances++;
    }

    ~Foo() {
        NumberOfInstances--;
    }
}

如果线程安全是一个问题,那么这个实现当然必须稍微改进一下。

编辑:正如迈克在他的评论中指出的那样,通过终结器实现这一点可能会在此上下文中导致严重的performance problems。因此,实现IDisposable并执行Dispose操作中的减量可能会更好。然而,这具有可能忘记设置物体的缺点。但是,我怀疑这将是一个严重的问题。

答案 1 :(得分:2)

我不知道第二个问题的答案,但第一个问题的答案可能是:

答案 2 :(得分:2)

听起来您希望尽可能多地保留已经计算过的数据,以便以后访问它。也许.NET 4.0中引入的MemoryCache类在您的情况下可能会有所帮助。

你可以这样做:

var cache = new MemoryCache("PathCache", new NameValueCollection()
{
  { "CacheMemoryLimitMegabytes", "256" }, // max 256 MB
  { "PhysicalMemoryLimit", "50" } // max 50% of RAM
});

// cache an item
cache["MyPath"] = "...";

// check, whether the cache contains an item
if (cache.Contains("MyPath"))
{
  // cache hit!
  var cachedPath = cache["MyPath"];
}

// ensure cache is released somewhere in your code
cache.Dispose();

答案 3 :(得分:0)

每个节点扩展都应查询数据,并且不将所有对象数据存储在内存中,只需存储每个节点的定义参数。选择节点时,显示查询中的数据。

答案 4 :(得分:0)

您可以利用工厂模式来创建实例,从而跟踪它们并管理您的记忆