gpt4 book ai didi

c# - 我可以告诉 .NET GC 不理会某些线程吗?

转载 作者:可可西里 更新时间:2023-11-01 03:11:30 24 4
gpt4 key购买 nike

我正在研究将相对较小的服务从 C++ 重写为 C# 的可能性。该服务有两个主要功能:

  1. 偶尔执行 HTTP 请求。它们涉及几个高级任务,例如 JSON 编码/解码、base64 编码/解码和 HTTP 请求本身,C++ 对此并不出色;
  2. 执行许多具有严格截止日期的实时音频相关任务,而 C# 对此并不出色。

实时任务由一个单独的库处理,该库执行自己的线程操作,几乎不与服务的其余部分交互。该服务的其余部分每 5 分钟左右向它提供一些从 HTTP 请求中获取的数据。

问题是,由于实时部分有严格的期限,我真的不能容忍库线程上的 GC 暂停。在我自己的代码方面,GC 应该有足够的时间在 Web 请求之间运行,但我不能容忍它在我尝试向库提供数据时启动。

found我可以创建一个关键部分,垃圾收集器不会在其中开始使用 GC.TryStartNoGCRegion() ,这解决了一半的问题。

但是,我仍然不知道是否有办法告诉 .NET GC 不理会不运行托管代码的特定线程。这可能吗?

最佳答案

正如您所指出的,当应用程序配置为在工作站 GC 模式下运行时,垃圾收集器不会暂停执行 native 代码的线程。在那种情况下,只要您的服务收到请求,我就会尝试这样的事情......

    private bool _running = true;
private int _workCounter = 0;
private AutoResetEvent _workFlag = new AutoResetEvent(false);
private void RunNoGCNativeCode(params object[] args)
{
// Increase the work counter to determine how many requests are being processed
if (Interlocked.Increment(ref _workCounter) == 1)
{
// Try to start a No GC Region
GC.TryStartNoGCRegion(1 * 1024 * 1024 * 1024, true);
}
// TODO: Prep data and execute your native code
// TODO: Process response
// TODO: Dispose of anything that is no longer in use and null objects as needed
if (Interlocked.Decrement(ref _workCounter) == 0 && GCSettings.LatencyMode == GCLatencyMode.NoGCRegion)
{
GC.EndNoGCRegion();
}
// Notify Manual Collection thread work has been completed
_workFlag.Set();
}

在不同的线程...

    private void WaitForNoWorkThenGC()
{
// Continue running thread while in use
while (_running)
{
// Wait for some work to be complete
_workFlag.WaitOne();
// If there is no work being processed call GC.Collect()
if (_workCounter == 0)
{
GC.Collect();
}
}
}

这应该可以帮助您控制 GC 发生的时间,以最大限度地减少对您的应用程序的影响

至于托管代码,我没有发现任何迹象表明 .NET 垃圾收集可以“不理会”执行托管代码的特定线程。垃圾收集的所有当前模式(服务器、工作站、并发等)都会在选择时暂停所有执行托管代码的线程。请注意,某些 GC 模式可以在线程中有更短的暂停,这也可能有所帮助。我也尝试在实时 C# 应用程序中使用 TryStartNoGCRegion() 并且它总是忽略我的请求,因为我使用的内存量,我找不到一种方法来指定仅在达到 X 内存限制后收集。

<罢工>

不过,您可以研究两种可能的解决方案。

    <罢工>
  1. 使用Garbage Collection Notifications监视 GC 何时接近完全垃圾回收。潜在地,如果您在内存到达收集点之前手动释放一些内存,您就可以避免垃圾收集。
  2. 在不同的应用程序进程中运行不同类型的请求?或者在收到它们时将它们传递给单独的应用程序流程。这样每个应用程序就不会共享上下文,垃圾回收将单独处理。

关于c# - 我可以告诉 .NET GC 不理会某些线程吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38728041/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com