之间使用哈希集的巨大性能差异.NET Framework 4.8和.NET 5



我遇到了应用程序非常慢的问题,因为有数千个处理程序连接到事件上,而删除这些处理程序非常慢。我的应用程序以运行。NET Framework 4.8进程,

我写了一个测试程序(但使用.NET 5(,用自己的实现替换了事件,在那里我使用HashSet存储处理程序,并自己实现事件的添加/删除处理程序。

我的测试应用程序运行得很好,但在将此解决方案应用于实际应用程序后,性能仍然很差。

我意识到运行时的差异似乎是原因。以下示例程序运行速度很快(在.NET 5上大约1秒,但如果在.NET Framework 4.8应用程序中运行相同的代码,则会运行几分钟(:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
namespace EventPerformaneMeasurement
{
class Program
{
private static void Main()
{
var sw = new Stopwatch();
var mc = new MyClass();
var list = Enumerable.Range(1, 1_000_000).Select(x => new PropertyChangedEventHandler((_, _) => { Console.WriteLine($"Handler {x} called"); })).ToList();

sw.Restart();
list.ForEach(handler=>mc.PropertyChangedNew += handler); 

sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);

sw.Restart();
list.ForEach(handler=>mc.PropertyChangedNew -= handler); 

sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
}
}
class MyClass
{
private HashSet<PropertyChangedEventHandler> _handlers = new();

public event PropertyChangedEventHandler PropertyChangedNew
{
add => _handlers.Add(value);
remove => _handlers.Remove(value);
}
}
}

我创造了两个。NET篡改来重现这种行为。NET fiddle要求我稍微更改一下示例代码的语法,并将迭代次数从1000000次减少到15000次,但性能差异仍然明显:

  • 。净4.7.2
  • 。净5

我不敢相信两者之间有这么大的区别。NET 5和。NET Framework 4.x的HashSet性能。

有人更了解这种影响吗?或者我可能被困在哪里了?有没有办法在中获得同样的性能。NET 4.8与另一种方式?

在这种情况下,由于我不能等到我们可以将产品切换到。NET 5中,我需要进行重构以不使用事件/委托,而是使用Oberserver模式和接口以及添加/删除侦听器方法。这样的观察者对象不会有这样弱的GetHashCode实现,所以HashSet将使用这样的观察器对象执行。。。

最新更新