Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.NETFramework4.8和.NET5之间的HashSet性能差异巨大_.net_Performance_Hashset_.net 5_.net 4.8 - Fatal编程技术网

.NETFramework4.8和.NET5之间的HashSet性能差异巨大

.NETFramework4.8和.NET5之间的HashSet性能差异巨大,.net,performance,hashset,.net-5,.net-4.8,.net,Performance,Hashset,.net 5,.net 4.8,我有一个问题,应用程序非常慢,因为有数千个处理程序连接到它的事件,删除这些处理程序非常慢。我的应用程序以.NET Framework 4.8进程运行 我编写了一个测试程序(但使用了.NET5),在该程序中,我用自己的实现替换了事件,在该实现中,我使用哈希集存储处理程序,并自己实现事件的添加/删除处理程序 我的测试应用程序工作得很好,但在将此解决方案应用到实际应用程序之后,性能仍然很差 我意识到运行时的差异似乎是原因。以下示例程序运行速度很快(在.NET 5上约为1秒,但如果在.NET Frame

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

我编写了一个测试程序(但使用了.NET5),在该程序中,我用自己的实现替换了事件,在该实现中,我使用哈希集存储处理程序,并自己实现事件的添加/删除处理程序

我的测试应用程序工作得很好,但在将此解决方案应用到实际应用程序之后,性能仍然很差

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

使用系统;
使用System.Collections.Generic;
使用系统组件模型;
使用系统诊断;
使用System.Linq;
命名空间事件性能度量
{
班级计划
{
私有静态void Main()
{
var sw=新秒表();
var mc=新的MyClass();
var list=Enumerable.Range(1,1_000_000)。选择(x=>newpropertychangedeventhandler((_,_)=>{Console.WriteLine($“Handler{x}调用”);})).ToList();
sw.Restart();
list.ForEach(handler=>mc.PropertyChangedNew+=handler);
sw.Stop();
控制台写入线(软件延迟毫秒);
sw.Restart();
list.ForEach(handler=>mc.PropertyChangedNew-=handler);
sw.Stop();
控制台写入线(软件延迟毫秒);
}
}
类MyClass
{
私有HashSet_handlers=new();
公共事件属性ChangedEventHandler属性ChangedNew
{
add=>\u handlers.add(值);
remove=>\u处理程序。remove(值);
}
}
}
我创建了两个.NET fiddle来重现这种行为,.NET fiddle要求我稍微更改示例代码的语法,并将迭代次数从1000000次减少到15000次,但性能差异仍然很明显:

我不敢相信.NET5和.NETFramework4.x在哈希集性能方面有这么大的差异


有人知道更多关于这种效应或者我可能被困在哪里吗?在.NET 4.8中,有没有其他方法可以获得相同的性能?

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

在这种情况下,由于我不能等待我们的产品切换到.NET 5,因此我需要重构以不使用事件/委托,而是将该模式用于接口和添加/删除侦听器方法。此类observer对象不会有如此弱的GetHashCode实现,因此HashSet将使用此类observer对象执行…

您应该从一个事实开始,即.NET Core/.NET 5在多个方面都比.NET Framework快得多,而且轻量级得多,因为大部分内容都是从头重写的。不确定是否可以在此处执行太多操作您是否在未连接调试程序的情况下运行它?(visual studio中的Ctrl+F5)我在没有调试程序的情况下进行了测试,因此没有附加调试程序。如果你看这两把小提琴,你会看到大约4000倍,2毫秒比8秒!我很惊讶.NET Framework中的这个用例竟然如此之慢……哈希表在很大程度上取决于一个好的GetHashCode()实现。与…相比。注意错误修复和不太理想的解决方法GetType()。GetHashCode()非常糟糕,因为它为每个委托对象提供了相同的哈希代码。这可能是因为他们需要修复列表,更改.NETFramework的实现太冒险了。你好,汉斯,谢谢。你的回答是正确的。它并没有解决我的问题,但它回答了我的问题,即在.NET Framework中是否真的可能存在这样的性能问题。如果您将您的评论作为答案,我会将其标记为正确答案。您应该从一个事实开始,即.NET Core/.NET 5在多个方面都比.NET Framework快得多,而且重量也轻得多,因为大部分内容都是从头重写的。不确定是否可以在此处执行太多操作您是否在未连接调试程序的情况下运行它?(visual studio中的Ctrl+F5)我在没有调试程序的情况下进行了测试,因此没有附加调试程序。如果你看这两把小提琴,你会看到大约4000倍,2毫秒比8秒!我很惊讶.NET Framework中的这个用例竟然如此之慢……哈希表在很大程度上取决于一个好的GetHashCode()实现。与…相比。注意错误修复和不太理想的解决方法GetType()。GetHashCode()非常糟糕,因为它为每个委托对象提供了相同的哈希代码。这可能是因为他们需要修复列表,更改.NETFramework的实现太冒险了。你好,汉斯,谢谢。你的回答是正确的。它并没有解决我的问题,但它回答了我的问题,即在.NET Framework中是否真的可能存在这样的性能问题。如果你把你的评论作为答案,我会把它标记为正确答案。
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);
        }
    }
}