管理类的实例数

JF *_*ier 4 c# out-of-memory

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

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

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

big*_*gge 5

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

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

作为第二步,我估计单个对象的大小.我强调在这种情况下进行估算是因为在C#中获取实际大小并不容易.然后,可以使用此估计值来设置N可以安全地实例化的最大对象数,而不会遇到OutOfMemoryException.

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

class Foo {

    private static NumberOfInstances = 0;

    public Foo() {
        NumberOfInstances++;
    }

    ~Foo() {
        NumberOfInstances--;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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