HAA0502 显式的新引用类型分配



我有ASP.Net Core 2.1C#应用程序。我正在使用Clr 堆分配分析器

https://marketplace.visualstudio.com/items?itemName=MukulSabharwal.ClrHeapAllocationAnalyzer

其中一种方法如下所示

前#1

public void ConfigureServices(IServiceCollection services) {
services.AddSingleton<IPocoDynamo>(serviceProvider => {
var pocoDynamo = new PocoDynamo(serviceProvider.GetRequieredService<IAmazonDynamoDB>());
pocoDynamo.SomeMethod();
return pocoDynamo;
});

}

例#2

public async Task<EventTO> AddEvent(EventTO eventObj)
{
try
{       
throw new Exception("Error!");
}
catch (Exception ex)
{
Logger.Log(ex, eventObj);
return null;
}
}

我在整个应用程序中使用 DI。但是,无论分析器在哪里找到关键字new,它都会发出警告

HAA0502 显式的新引用类型分配

此外,无论在哪里使用 Lambda 表达式,它都会发出警告(如 ex#1(

Warning HAA0301 Heap allocation of closure Captures:

是什么原因导致这种情况以及如何解决这个问题?

谢谢!

分配分析器用于标记代码执行的所有分配。这不是您希望始终保持打开的内容:考虑以下愚蠢的代码

public static string MyToString(object? o)
{
if (o == null)
throw new ArgumentNullException(nameof(o)); // HAA0502 here
return o.ToString() ?? string.Empty;
}

分析器将以警告的形式发出HAA0502作为标记行上的信息,告诉您正在分配新实例。现在,在这种情况下,很明显您正在做什么,这是一个微不足道的警告,但分析器的目的是帮助您发现可能使代码变慢的令人讨厌的分配。

现在在这里考虑这个愚蠢的代码:

public static void Test1()
{
for (int i = 0; i < 100; i++)
{
var a = i + 1;
var action = new Action(
() =>   // HAA0301 Heap allocation of closure Capture: a
{
Console.WriteLine(a);
}
);
action();
}
}

除了HAA0502因为我们正在创建一个新对象而被标记在new Action(之外,lambda 上还有一个额外的警告:HAA0301。这就是为什么分析器变得更有用的原因:在这里,分析器告诉您运行时将创建一个包含捕获的变量a的新对象。如果你不熟悉这一点,你可能会认为该代码被转换为这样的东西(仅用于解释目的(:

private sealed class Temp1
{
public int Value1 { get; }
public Temp1(int value1)
{
Value1 = value1;
}
public void Method1()
{
Console.WriteLine(Value1);
}
}
public static void Test1()
{
for (int i = 0; i < 100; i++)
{
var a = i + 1;
var t = new Temp1(a);
t.Method1();
}
}

在后一个代码中,很明显,在每次迭代中,您都在分配一个对象。

您可能遇到的主要问题是:分配对象是一个问题吗?在 99.9% 的情况下,这不是问题,您可能会接受编写可读、精确和简洁的代码的简单性,而无需处理低级细节,如果您遇到性能问题(即剩余的 0.01%(,分析器可以非常方便,因为它在一个镜头中显示您或代表您的编译器正在分配一些东西。分配对象需要将来的垃圾回收器周期来回收内存。

关于您的代码,您正在使用工厂模式通过 DI 初始化服务:该代码运行一次。因此,您分配新对象也就不足为奇了。因此,您可以安全地禁止显示这部分代码的警告。您可以使用 IDE 生成抑制代码。这就是为什么我建议禁用分析器并仅在搜寻性能问题时才启用它。

相关内容

最新更新