Roslyn 导致内存泄漏,我该如何遏制它?

问题描述 投票:0回答:1

所以我有这个 NET6.0 控制台应用程序,它充当其他 UDP 消息应用程序之间的桥梁。

要定义如何从我的应用程序发送数据,请使用此配置文件系统,该系统由十几个文件组成,其中定义了每个数据结构的所需变量。在启动时,我读取每个文件,并为文件中定义的每个数据结构编写一个字符串,该字符串表示我想要用来为每个配置文件生成自定义字符串的方法,然后使用 Roslyn 对其进行编译以创建委托以供以后使用(通过Microsoft.CodeAnalysis.CSharp.Scripting NuGet 包):

ScriptRunner<string> scriptToAdd = CSharpScript.Create<string>(toConvert, globalsType: WorldData.GetTypeByName(tempName)).CreateDelegate();

虽然它是一个控制台应用程序,只有很少的配置文件,但它按预期工作,但现在我必须为这个应用程序提供一个 Web 界面(我通过创建 Blazor 项目并引用原始项目来做到这一点),现在在启动时我得到一个 Out Of内存异常。

经过一些研究,我发现 Roslyn 在编译某些代码时会加载所有必要的程序集,但随后不会卸载它们。

我做的第一件事就是验证 Roslyn 确实是罪魁祸首,所以我跳过了委托创建,它就像一个魅力。

下一步是确定我是否可以在 Roslyn 处理完程序集后卸载它们,然后我发现了 AssemblyLoadContext,但由于超出了我的知识范围,我寻求了 GitHub Copilot 的帮助,它给了我这段代码:

var context = new AssemblyLoadContext("ScriptContext", isCollectible: true);

try
{
    scriptToAdd = CSharpScript.Create<string>(
        toConvert,
        globalsType: WorldData.GetTypeByName(tempName),
        options: ScriptOptions.Default.WithReferences(
            context.LoadFromAssemblyPath(typeof(object).Assembly.Location)
        )
    ).CreateDelegate();
}
finally
{
    context.Unload();
}

作为一个相对缺乏经验的开发人员,这看起来很有希望,我知道需要多次调用 LoadFromAssemblyPath 才能获取所需的每个程序集,但我想尝试一下。 然后我得到这个错误:

System.IO.FileLoadException:“无法加载文件或程序集“System.Private.CoreLib,版本= 6.0.0.0,文化=中性,PublicKeyToken = 7cec85d7bea7798e”。”

在这一点上,我已经超出了我的范围,除了这篇文章之外找不到更多的东西,但正如我已经说过的......远远超出了我的范围。

提前感谢任何愿意帮助我的人。让我知道我是否可以以及还可以提供什么来帮助您帮助我。

c# assembly delegates console-application roslyn
1个回答
0
投票

首先,这不是内存泄漏,这是 Roslyn 的预期工作方式。它以内存使用量(通过尽可能多、尽可能频繁地缓存大量数据)来换取速度,以允许在 VS 中的每次按键时进行近实时编译,包括用户定义的分析器和源代码生成。效果很漂亮!

我遇到内存不足异常

我要检查的第一件事是您的应用程序是否未在 32 位模式下运行。 .Net 应用程序十多年来一直不打算在 32 位模式下运行。在 64 位模式下,您永远不会遇到内存不足的异常。

然后它不会卸载它们

由于 JIT 的工作方式,一旦加载了程序集,您就无法卸载它们。最多你可以通过函数调用来清理数据结构,但 Roslyn 是为了性能而设计的,因此它管理自己的内存并且不提供用户可见的清理函数。

有了这个,如果您仍然想减少总体内存使用量,您实际上有两个选择:

  1. 使用 Roslyn 作为外部进程,从源代码中创建
    .dll
    程序集,然后引用它并像现在一样使用它(使用委托)。这样,当编译器进程终止时,缓存就会消失。
  2. 根本不使用Roslyn,直接将IL指令发送到内存。这确实不难,特别是如果您保持生成的代码简单(例如,通过创建辅助函数来调用,如果您需要对字段进行处理)。
© www.soinside.com 2019 - 2024. All rights reserved.