GC 暂停导致性能问题

发布于 2024-12-28 13:20:04 字数 240 浏览 2 评论 0原文

我刚刚开始研究一个项目(我是新项目,不是这个项目),作为性能优化,将 32GB 的图形数据(节点、边等)加载到内存中并将其保留在那里。这是一项长期运行的服务,因此数据应在服务的生命周期内保留在内存中。当 CLR 触发第 2 代收集时,(当然)会出现较大的暂停,这会损害性能,同时 GC 会扫描第 2 代,将所有内容标记为可到达对象。

我想知道的是,是否有可用于必须在内存中保存大量数据的托管应用程序的策略?阻止 Gen 2 集合运行的最佳方法是什么?

I just started working on a project (I'm new not the project) that as a performance optimization loads 32GB of graph data (nodes, edges, etc) into memory and keeps it there. This is a long running service so the data is meant to remain in memory for the lifetime of the service. When a Gen 2 collection is triggered by the CLR there are large pauses (of course) which hurt performance while the GC scans Gen 2 marking everything as reachable objects.

What I'd like to know is are there strategies available for managed applications that must keep large amounts of data in memory? What are the best ways to prevent Gen 2 collections from running - ever?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

韶华倾负 2025-01-04 13:20:04

您可以在实现中执行一些常规操作,以使其更加 GC 友好:一个相对简单的操作是减少对象图中的对象引用数量。例如,替换:

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

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

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

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

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

或适合您设计的类似内容。这减少了收集器必须遍历的对象图中的指针数量。

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

There are a few general things that you can do in your implementation to make it more GC friendly: a relatively easy one is to reduce the number of object references in your object graph. For example, replace:

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

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

With indirect references through Node identifiers:

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

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

or something similar that fits your design. This reduces the number of pointers in the object graph that the collector has to walk.

Shifting the data on to the native heap is another possibility, writing a small JNI library to give you the interface to perform the operations you need. This can pay off in other ways: the last time I had a similar problem to solve we made substantial space savings through this approach because we had largely western textual data in the data set, which occupied far less space encoded as UTF8. As long as the cost of your graph search is non-trivial then the overhead of the native call is not likely to be an issue.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文