我通常可以将 GC 模式设置为 SustainedLowLatency 多长时间

How long can I typically keep GC mode set to SustainedLowLatency

我有一个服务器应用程序,它每秒从多个传感器接收大量 UDP 数据包 50 次(每 20 毫秒接收一个新数据包),进行一些分析、存储它们、进行一些调试日志记录和其他“服务器内容”。

问题是 GC 每隔一段时间执行一次完全阻塞收集,暂停 所有线程 长达 200 毫秒(在某些罕见的百分位数中可能更长时间)。我对每个数据包滞后几毫秒没有问题(即使每个数据包持续延迟 10 毫秒也不是问题),但长时间暂停真的很烦人。

根据 MSDN,GC 有 SustainedLowLatency mode,根据 MSDN:

Enables garbage collection that tries to minimize latency over an extended period. The collector tries to perform only generation 0, generation 1, and concurrent generation 2 collections.

Full blocking collections may still occur if the system is under memory pressure.

  1. “延长期”是否仍然意味着我不能简单地将模式设置为SustainedLowLatency然后忘记它?

  2. 有什么方法可以防止完全阻塞收集,至少对于单核而言?

基本上,此模式将尝试仅使用后台 gen 2 收集,并且仅在系统开始缺乏内存时才执行完整的 GC。阻塞收集之间的延迟完全取决于您的代码:您使用第 2 代的次数越少,内存碎片就越少,并且持续时间越长。不幸的是,套接字使用固定缓冲区,这是内存碎片的典型原因。您可以尝试重用缓冲区,但这涉及使用套接字编写棘手的低级代码 API.

防止完全阻塞集合的唯一方法是在需要大型数组时使用TryStartNoGCRegion. There again, how much you can last depends on how much memory you allocate. Use small objects. Use structs instead of classes whenever possible. Use pooling

分析(例如,使用 Jetbrains dotTrace)将帮助您发现和优化分配大量内存的代码路径。