百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

是什么让 .Net Core 性能碾压传统 .Net(二)?

cac55 2024-10-11 11:02 14 浏览 0 评论

序列化

二进制序列化是.NET的另一个领域。BinaryFormatter最初并不是.NET Core中的一个组件,但是它包含在.NET Core 2.0中。该组件在性能方面有比较巧妙的修复。例如,PR dotnet / corefx#17949是一种单行修复,可以增加允许增长的最大大小的特定数组,但是这一变化可能对吞吐量产生重大影响,通过O(N)算法比以前的O(N ^ 2)算法要话费更长的操作时间。以下代码示例,明显的展示了这一点:

using System;using System.Collections.Generic;using System.Diagnostics;using System.IO;using System.Runtime.Serialization.Formatters.Binary;class Test

在.NET 4.7中,代码输出如下结果:

76.677144

而在.NET Core 2.0中,会输出如下结果:

6.4044694

在这种情况下显示出了12倍的吞吐量提高。换句话说,它能够更有效地处理巨大的序列化输入。

文字处理

.NET应用程序中另一种很常见的计算形式就是处理文本,文字处理在堆栈的各个层次上都有大量的改进。

对于正则表达式,通常用于验证和解析输入文本中的数据。以下是使用Regex.IsMatch重复匹配电话号码的示例:

using System;using System.Diagnostics;using System.Text.RegularExpressions;public class Test

在个人计算机上,.NET 4.7会得到的如下结果:

Elapsed=00:00:05.4367262 Gen0=820 Gen1=0 Gen2=0

而使用.NET Core 2.0会得到如下结果:

Elapsed=00:00:04.0231373 Gen0=248

由于PR dotnet / corefx#231的变化很小,这些修改有助于缓存一部分数据,因此吞吐量提高了25%,分配/垃圾收集减少了70%。

文本处理的另一个例子是各种形式的编码和解码,例如通过WebUtility.UrlDecode进行URL解码。在这种解码方法中,通常情况下输入不需要任何解码,但是如果输入经过了解码器,则输入仍然可以通过。感谢来自hughbe的 PR dotnet / corefx#7671,这种情况已经被优化了。例如下面这段程序:

using System;using System.Diagnostics;using System.Net;public class Test

在.NET 4.7中,会得到以下输出:

Elapsed=00:00:01.6742583 Gen0=648

而在.NET Core 2.0中,输出如下:

Elapsed=00:00:01.2255288 Gen0=133

其他形式的编码和解码也得到了改进。例如,dotnet / coreclr#10124优化了使用一些内置Encoding -derived类型的循环。例如下面的示例:

using System;using System.Diagnostics;using System.Linq;using System.Text;public class Test

在.NET 4.7中得到以下输出,如:

00:00:02.4028829

而.NET Core 2.0等到如下输出:

00:00:01.6133550

这些改进也适用于字符串和其它类型之间转换,例如.NET中生成Parse和ToString方法。使用枚举来表示各种状态是相当普遍的,例如使用Enum.Parse将字符串解析为相应的枚举。PR dotnet / coreclr#2933改善了这一点。请查看以下的代码:

using System;using System.Diagnostics;public class Test

在.NET 4.7中,会得到的以下结果:

Elapsed=00:00:00.9529354 Gen0=293

在.NET Core 2.0上,会得到以下结果:

Elapsed=00:00:00.6448327 Gen0=11

不但吞吐量提高了约33%,而且分配和相关垃圾收集也减少了约25倍。

当然,在.NET应用程序中需要进行大量的自定义文本处理,除了使用像Regex / Encoding这样的内置类型和Parse和ToString这样的内置操作之外,文本操作通常都是直接构建在字符串之上,并且大量的改进已经引入到了操作on String之上。

例如,String.IndexOf很擅长于查找字符串中的字符。IndexOf在bnetyersmyth的dotnet / coreclr#5327中得到改进,他们为String实现了一系列的性能改进。正如下面的例子:

using System;using System.Diagnostics;public class Test

在.NET 4.7上,会得到如下结果:

00:00:05.9718129

而在.NET Core 2.0中,会得到如下结果:

00:00:03.1283763

吞吐量提高约2倍。

下面是比较字符串部分。这是一个使用String.StartsWith和序数比较的例子:

using System;using System.Diagnostics;using System.Linq;public class Test

在.NET 4.7上会得到如下结果:

00:00:01.3097317

.NET Core 2.0会得到如下结果:

00:00:00.6239002

对String的改进,也让我们看到对于其它方面进行更多改进的可能性,这是非常有趣的。

文件系统

到目前为止,本文一直专注于内存中操纵数据的各种改进。但是.NET Core的许多更改都是关于I / O的。

下面从文件开始介绍。这是一个从文件中异步读取所有数据并将其写入另一个文件的示例:

using System;using System.Diagnostics;using System.IO;using System.Threading.Tasks;class Test

FileStream中的开销也在进一步减少,例如DOTNET / corefx#11569增加了一个专门的CopyToAsync实现,dotnet/ corefx#2929也改进了异步写入的处理,.NET 4.7会得到如下结果:

Elapsed=00:00:09.4070345 Gen0=14 Gen1=7 Gen2=1

.NET Core 2.0会得到如下结果:

Elapsed=00:00:06.4286604 Gen0=4 Gen1=1 Gen2=1

网络

网络是值得关注的部分,这部分也将取得很大的改进。目前正在付出很大的努力来优化和调整低等级的网络堆栈,以便高效地构建更高级别的组件。

这种改变带来的一个很大的影响是PR dotnet / corefx#15141。SocketAsyncEventArgs是Socket上大量异步操作的核心,它支持同步完成模型,因此异步操作实际完成了同步操作,这样避免了异步操作的分配消耗。但是,.NET 4.7中的同步操作运算是失败的, PR修复了上述的实现问题,允许在socket上进行所有异步操作的同步完成。这样的提升在以下代码中变现的非常明显:

using System;using System.Diagnostics;using System.Net;using System.Net.Sockets;using System.Threading;using System.Threading.Tasks;class Test

该程序创建两个连接的socket,然后向socket写入1000次,并且在案例中使用异步方法接收,但绝大多数操作将同步完成。在.NET 4.7中会得到如下结果:

Elapsed=00:00:20.5272910 Gen0=42 Gen1=2 Gen2=0

在.NET Core 2.0中,大多数操作能够同步完成,得到如下结果:

Elapsed=00:00:05.6197060 Gen0=0 Gen1=0 Gen2=0

不仅仅是直接使用socket来实现组件的这种改进,而且还通过更高级别的组件来间接使用socket,其他PR的结果是更高级别组件(如NetworkStream)的额外性能提升。例如,PR dotnet / corefx#16502在SocketAsyncEventArgs上重新实现了基于Socket的SendAsync和ReceiveAsync操作,并且允许它们在NetworkStream中使用。Read / WriteAsync和PR dotnet / corefx#12664添加了一个专门的CopyToAsync重写,以便更有效地从NetworkStream读取数据并将其复制到其他流中。这些变化对NetworkStream吞吐量和分配有非常大的影响。看看下面这个例子:

using System;using System.Diagnostics;using System.IO;using System.Net;using System.Net.Sockets;using System.Threading;using System.Threading.Tasks;class Test

与之前的Socket一样,下面我们创建两个连接的socket,然后把它们包含在NetworkStream中。在其中一个流中,我们将1K数据写入一百万次,而另一个流则通过CopyToAsync操作读出所有数据。在.NET 4.7中,会得到如下输出:

Elapsed = 00:00:24.7827947 Gen0 = 220 Gen1 = 3 Gen2 = 0

而在.NET Core 2.0中,时间减少了5倍,垃圾回收有效地减少到零:

Elapsed=00:00:05.6456073 Gen0=74 Gen1=0 Gen2=0

其它网络相关组件也将得到进一步优化。例如SslStream通常将围绕在NetworkStream中,以便向连接中添加SSL。下面的示例将看到这种影响,这个示例将在NetworkStream之上添加SslStream的用法:

using System;using System.Diagnostics;using System.Threading;class Test

在.NET 4.7中,会得到如下结果:

Elapsed=00:00:21.1171962 Gen0=470 Gen1=3 Gen2=1

.NET Core 2.0包含了诸如dotnet / corefx#12935和dotnet / corefx#13274等PR的改进,这两者都将大大减少了使用SslStream所涉及的分配。在.NET Core 2.0上运行相同的代码时,会得到如下结果:

Elapsed=00:00:05.6456073 Gen0=74 Gen1=0 Gen2=0

85%的垃圾收集已被删除!

并发

对于并发和并行性相关的原始化和基础部分,也得到了许多改进。

这里的一个关键点是ThreadPool,它是执行许多.NET应用程序的核心。例如,PR dotnet / coreclr#3157减少了QueueUserWorkItem中涉及的某些对象的大小,PR dotnet / coreclr#9234使用了ConcurrentQueue <T>重写来替换ThreadPool的全局队列,其中会用到较少的同步和分配。从以下的示例中,会看到最终结果:

using System;using System.Diagnostics;using System.Threading;class Test

在.NET 4.7中,会等到如下结果:

Elapsed=00:00:03.6263995 Gen0=225 Gen1=51 Gen2=16

而在.NET Core 2.0中,会得到如下结果:

Elapsed=00:00:02.1797508 Gen0=153 Gen1=0 Gen2=0

这是一个巨大的吞吐量的改善,并且这样一个核心组件的垃圾量也将大幅减少。

同步原语也在.NET Core中得到提升。例如,低级并发代码通常使用SpinLock来尝试避免分配锁定对象或最小化竞争锁所花费的时间。PR dotnet / coreclr#6952改进了失败的快速路径,以下测试会得到显而易见的结果:

using System;using System.Diagnostics;using System.Threading;class Test

在.NET 4.7中,会得到如下结果:

00:00:02.3276463

而在.NET Core 2.0中,会得到如下结果:

00:00:00.3915327

吞吐量的这种差异可能会对运行这种锁的热路径产生很大的影响。

这只是众多例子中的一个。另一个例子围绕着Lazy<T>,它被PR dotnet / coreclr#8963用manofstick重写,以便提高访问初始化过的Lazy <T>的效率。这样的提升效果从下面的示例中清晰可见:

using System;using System.Diagnostics;class Test

在.NET 4.7中,会得到的结果如下:

00:00:02.6769712

而在.NET Core 2.0中,会得到的结果如下:

00:00:00.5278348

吞吐量增加约5倍。

下一步是什么

本文只涉及了部分.NET Core的性能改进。在dotnet / corefx和dotnet / coreclr repos 中的pull请求中搜索“perf”或“performance”,你会发现接近一千个合并的PR改进。其中一些是比较大的同时也很有影响力的改进,而另一些则主要减少了库和运行时的消耗,这些变化一起起作用,保证了能够在.NET Core上更快的运行应用程序。展望未来,性能将成为关注的重点,无论是以性能改进为目标的API还是现有库的性能的改进。

欢迎大家深入了解.NET Core代码库,以便找到影响自己的应用程序和库的瓶颈,并提交PR来修复它们。如果你的问题得到修复,也请将修复程序分享给所有需要的人。

转载请注明出自:葡萄城控件

关于葡萄城

葡萄城是全球控件行业领导者,世界领先的企业应用定制工具、企业报表和商业智能解决方案提供商,为超过75%的全球财富500强企业提供服务。

相关推荐

三星电视通过VGA端口接连笔记本教程

科技的发达不仅仅表现于智能电视的功能有多全面,手机、笔记本、电视盒子有多智能,而是这些电子产品是否能够相互连接、多屏互动进而进行多媒体播放与数据传输等。目前,三星电视早已可以实现多项设备间的连接与使用...

KVM210UA 2口USB电脑切换器VGA KVM切换器 键鼠控制2台电脑 免电源

登昌恒KVM210UA2口USB电脑切换器VGAKVM切换器键鼠控制2台电脑免外接电源即时切换显示画面不延迟热插拔免驱动适合MAC苹果电脑笔记本和台式电脑...

大神自己将老旧笔记本改装成多方面强悍的“超极本”

文/自己建房子亲戚有个03年的清华紫光笔记本,配置是奔腾1.8G,XP勉强运行,亲戚今年帮了非常大的忙,无以回报,把他这个垃圾本改一下略为回报新配置:CPU是i53470t的,内存是4G两条组成双...

正点原子开拓者FPGA开发板资料连载第二十二章RGBTFT-LCD彩条显示

1)实验平台:正点原子开拓者FPGA开发板2)摘自《开拓者FPGA开发指南》关注官方微信号公众号,获取更多资料:正点原子3)全套实验源码+手册+视频下载地址:http://www.openedv.c...

显卡引出故障现象及排除(造成显卡故障的原因有哪些)

故障现象一:显示器黑屏故障排除:1、先确定是否是显卡有问题。判断的方法是听PC喇叭的叫声,一长两短声肯定是显卡发生了致命错误,只能更换。2、如果无法断定显卡的好坏,可以换一块试试,还不行的话则有几种情...

用FPGA/树莓派RP2040驱动HDMI的资源

如果能够用FPGA能够驱动显示器,就可以做不少与视频相关的实验,很多FPGA开发板使用了比较简单的VGA接口,连接非常简单,如下图:然后我们就可以用FPGA的逻辑来做各种游戏了:然而,现在的显示器基本...

STM32+A3P125 图形控制器方案,多参数监护仪数据采集模块深度解析

一、生理信号采集与转换架构多参数监护仪数据采集模块是将人体生理信号转化为数字信号的核心单元,其架构遵循“传感器感知→信号调理→模数转换→数字处理”的标准化流程:1.传感器类型与生理信号转换传感器...

电脑重启都提示AMD显卡错误“No AMD graphics driver is..”解决方法

电脑重装完系统后,每次重启都提示AMD显卡错误“NoAMDgraphicsdriveris......”怎么办?网上相关问题解决很多人方法是打驱动,可是有些是驱动打好了还是反复出现NoAM...

ipad1改造显示器之拆解篇(ipadair改显示器)

闲来无事,翻出来家里12年前的初代ipad,除了能正常充电开机盖泡面之外,好像啥也干不了……上网一搜有许多改成显示器的案例,按耐不住的激动的小手也想跃跃欲试一番,说干就干,先从拆解开始。注意,以hom...

老电脑显卡驱动装不上?降级旧版驱动一招解决!

老电脑显卡驱动装不上?降级旧版驱动一招解决!今天给家里的老台式机重装系统遇到了麻烦:i34130处理器配上HD7770显卡,装完Win7后,显卡驱动死活装不对!问题表现:最初状态:设备管理器“显...

想淘汰VGA 先得知道这些门道(vga是不是淘汰了)

不要说新显卡,就是在主板上,VGA接口也越来越少,眼看就被彻底淘汰了。当然小伙伴们的显示器应该早就不是只有VGA接口的旧型号了,彻底淘汰VGA就换个接口或者弄个转接呗,可是……真的这么简单吗?小编今天...

IMX258摄像头驱动(摄像头最新驱动)

IMX25813MPOISUSBCamera(A)说明IMX25813MPOISUSBCamera(A)功能简介特性USB通用摄像头1300万像素接口USB...

朗强科技:VGA视频信号分配原理分析

VGA分配器的主要功能是把一个视频信号重新分配成多个信号。高分辨率的视频分配放大器的作用是在接收一个来自计算机视频端口的信号后将其进行放大处理,并且在保持原有信号质量的情况下,将其信号分配到多个高分辨...

视频矩阵的应用及分类(视频矩阵的应用及分类)

视频矩阵-基本功能和要求视频矩阵-基本功能和要求  一个矩阵系统通常还应该包括以下基本功能:字符信号叠加;解码器接口以控制云台和摄像机;报警器接口;控制主机,以及音频控制箱、报警接口箱、控制键盘等附件...

告别蓝屏烦恼,Windows系统崩溃急救指南!

Windows系统蓝屏(BlueScreenofDeath,简称BSoD)是Windows操作系统在无法从系统错误中恢复时显示的屏幕图像,通常会伴随一个或多个错误代码,这些代码是诊断问题的关键线...

取消回复欢迎 发表评论: