2012-01-23 128 views
1

我刚刚开始研究一个项目(我不是新项目),因为性能优化会将32GB图形数据(节点,边等)加载到内存中并保留在内存中。这是一项长期运行的服务,因此数据意味着在服务的整个生命周期内保留在内存中。当CLR触发Gen 2采集时,会有大量暂停(当然),从而影响性能,而GC则会扫描Gen 2,将所有事件都标记为可访问对象。导致性能问题的GC暂停

我想知道的是,有哪些策略可用于托管应用程序,它们必须将大量数据保存在内存中?什么是防止第二代集合运行的最佳方式 - 曾经?

+0

如果你从未运行第二代,你会泄漏使它成为第二代的物体,但它们不会永远活着。根据你的应用程序的作用,这可能是很多对象。 – delnan

+0

对不起,你是对的。但是有没有可以防止这种长时间停顿的策略?或者使用托管运行时实现这种应用程序是一个坏主意? –

+0

@itadapter谢谢。我不再为那家公司工作,但那是我们最终做的 - 对非托管状态进行编组 - 而且你是对的,它解决了问题。 –

回答

1

在你的实现中你可以做一些普通的事情来使它更友好:一个相对容易的就是减少对象图中对象引用的数量。例如,替代:

class Graph { 
    List<Node> roots; 
    // ... 
} 

class Node { 
    Node[] outwardEdges; 
    // ... 
} 

间接引用,通过节点的标识符:

class Graph { 
    List<Node> roots; 
    Node[] allNodes; 
    // ... 
} 

class Node { 
    int[] outwardEdges; 
    // ... 
} 

或类似的东西适合你的设计。这减少了收集器必须行走的对象图中的指针数量。

将数据转移到本地堆上是另一种可能性,即编写一个小的JNI库,为您提供执行所需操作的界面。这可以通过其他方式得到回报:上次我遇到类似问题需要解决时,我们通过这种方法节省了大量空间,因为我们在数据集中主要使用了西方文本数据,因此占用的空间少得多,编码为UTF8。只要图搜索的成本不是微不足道的,那么本地调用的开销就不太可能成为问题。