《ASP.NET Core 高性能系列》致敬伟大的.NET斗士甲骨文!
写在开始
三年前,曾写过一篇文章:从.NET和Java之争谈IT这个行业,当时遭到某些自认为懂得java就了不起的Javaer抨击,
现在可以致敬伟大的.NET斗士甲骨文了
(JDK8以上都需要收费,Android弃用java作为第一语言,别高兴:OpenJDK是甲骨文的).
《ASP.NET Core 高性能系列》是一套如何编写高性能Web应用技术系列文章,
我们将从.NET 2开始全面升入.其中我们会讨论互联网当今热门的技术话题:容器、容器编排、服务治理、RPC等
此文是第一篇,用于此系列的开门篇,后面每周会持续发布.
一、Core 2中需要知道的新鲜东西
Core系列有两个主要产品:
第一个是.NET Core
它是一个低级别的提供基本库的框架。 它可以用来编写控制台应用程序,它也是
更高级别的应用程序框架的基础。
第二个是ASP.NET Core
它是一个用于构建Web的跨平台框架
另外.NET Core中的更改也将适用于ASP.NET Core,因为这是基础
二、.NET Core 2的新东西
2.1 API范围更加广泛
.NET Core 2的主要焦点是API范围的大幅增加,在1.*的基础上增加了两倍的API,
而且支持.net standard,您也可以引用.NET Framework程序集而无需重新编译,
只要程序集中的API已在.NET Core中实现就可以正常工作。这意味着更多的Nuget包可以在.NET Core中工作,
ASP.NET Core Library and Framework 支持情况的一个统计站点:https://ANCLAFS.com(有点跟不上了)
2.2 性能的大幅度提升
.NET Core 2.0中一些更有趣的变化是在原始的.NET FrameworkAPI上性能改进
,已经对许多框架的实现进行了调整了数据结构。
下面是一些已经看到快速改进的类和方法,已经内存开销的减少包括:
- List<T>
- Queue<T>
- SortedSet<T>
- ConcurrentQueue<T>
- Lazy<T>
- Enumerable.Concat()
- Enumerable.OrderBy()
- Enumerable.ToList()
- Enumerable.ToArray()
- DeflateStream
- SHA256
- BigInteger
- BinaryFormatter
- Regex
- WebUtility.UrlDecode()
- Encoding.UTF8.GetBytes()
- Enum.Parse()
- DateTime.ToString()
- String.IndexOf()
- String.StartsWith()
- FileStream
- Socket
- NetworkStream
- SslStream
- ThreadPool
- SpinLock
另外,对于.NET Core 2的RyuJIT Just In Time编译器进行了改进。
仅作为一个示例就能说明说明其优秀之处,finally块现在几乎与不使用异常一样高效,
这在没有抛出异常的正常情况下是有益的。您现在没有理由不使用try和using{}块,以及checked检查
三、ASP.NET Core 2的新东西
ASP.NET Core 2利用了.NET Core 2的所有改进,不仅通过即时编译处理程序缩短了启动时间,
涵盖了增加了输出缓存,本地及分布式缓存(SQLSERVER,REDIS).
3.1 metapackage
.NET Core包含了一个新metapackage,所以你只用引用一个NuGet项就可以得到所有的东西,metapackage仍然由单个独立的包组成,
一个新的包修剪功能(new package-trimming)确保如果您不使用包,那么它的二进制文件将不会包含在您的部署中,
即使您使用metapackage 来引用它。设置Web主机配置也有合理的默认设置。
您无需单独添加logging, Kestrel, and IIS。logging也变得更简单,因为它是建立的在,你再也没有任何借口不一开始就使用它
3.2 Razor Pages
无控制器Razor Pages。 这正是它听起来的样子,而且它允许您使用Razor模板编写页面。
它类似于Web Pages产品,不必和WebForm混淆。 大家其实觉得是WebForm的卷土重来,个人感觉是满怀希望的卷土重来,
架构做了更多抽象和思考,不会像之前一样,带来如此多的状态与之相伴.
3.3 新的authentication 模型
新的 authentication 模型能让更好地使用了依赖注入, ASP.NETCore Identity 允许你使用OpenID 、OAuth 2
来为你的API获取访问tokens .当然你可以研究Identity Server 4 项目,它提供了相同的功能.
3.4 表单请求自动防伪
你不必再为表单添加防伪token(防止跨越伪造请求) (之前你不得不添加一个attribute在Post方法中进行验证),
现在这一切都是自动的.
3.5性能提升
ASP.NET Core有一些额外的与.NET Core无关的性能提升:
启动时间通过即时编译处理明显减少,虽然这不是ASP.NET Core 2的新功能;
output caching依然可用,在1.0时,只有response caching*(简化了如何设置http header),
1.1 时,添加了memory cache,现在你可以还使用分布式缓存()SQL Server or Redis)
四 .NET Standard 2.0
.NET Standard 是一套正式的 .NET API 规范,目标是在所有 .NET 实现中推出。 推出 .NET Standard 的背后动机是要提高 .NET 生态系统中的一致性。
ECMA 335 持续为 .NET 实现行为建立统一性,但适用于 .NET 库实现的 .NET 基类库 (BCL) 没有类似的规范。
.NET Framework 4.6.1实现了.NET Standard 2.0.
.NET Standard 可实现以下重要情境:
1.为要实现的所有 .NET 实现定义一组统一的、与工作负荷无关的 BCL API。
2.使开发人员能够通过同一组 API 生成可在各种 .NET 实现中使用的可移植库。
3.减少甚至消除由于 .NET API 方面的原因而对共享源代码进行的条件性编译(仅适用于 OS API)。
五、C# 6.0语言级别的新东西
5.1 属性可以连带赋值
- public DateTime BirthDay { get; set; } = DateTime.Now.AddYears(-);
5.2 导入静态类
- using static System.Math;
- Console.WriteLine($"导入后可直接使用方法: {Pow(4, 2)}");
5.3 字符串格式化的变化
- Console.WriteLine(string.Format("当前时间:{0}",DateTime.Now.ToString()));
5.4 空值运算符
- Console.WriteLine(name?.ToString()); // 程序不会报错,也不会输出任何值
5.5 对象初始化器
可以通过索引的方式进行赋值
- IDictionary<int, string> dictNew = new Dictionary<int, string>()
- {
- [4] = "first",
- [5] = "second"
- };
5.6 异常过滤器
- int exceptionValue = 10;
- try
- {
- Int32.Parse("s");
- }
- catch (Exception e) when (exceptionValue > 1)//满足条件才进入catch
- {
- Console.WriteLine("catch");
- }
5.7 nameof表达式
- Console.WriteLine(nameof(People));
5.8 在属性/方法里面使用Lambda表达式
- public void Print() => Console.WriteLine(Name);
六、C# 7.0语言级别的新东西
6.1 out变量不需要申明了
- var input = ReadLine();
- if (int.TryParse(input, out var result))
- {
- WriteLine("您输入的数字是:{0}",result);
- }
- else
- {
- WriteLine("无法解析输入...");
- }
6.2元组
元组(Tuple)在 .Net 4.0 的时候就有了,但元组也有些缺点,如:
1)Tuple 会影响代码的可读性,因为它的属性名都是:Item1,Item2.. 。
2)Tuple 还不够轻量级,因为它是引用类型(Class)。
备注:上述所指 Tuple 还不够轻量级,是从某种意义上来说的或者是一种假设,即假设分配操作非常的多。
C# 7 中的元组(ValueTuple)解决了上述两个缺点:
1)ValueTuple 支持语义上的字段命名。
2)ValueTuple 是值类型(Struct)。
传统的创建方式
- var tuple = (1, 2); // 使用语法糖创建元组
- var tuple2 = ValueTuple.Create(1, 2); // 使用静态方法【Create】创建元组
- var tuple3 = new ValueTuple<int, int>(1, 2); // 使用 new 运算符创建元组 WriteLine($"first:{tuple.Item1}, second:{tuple.Item2}, 上面三种方式都是等价的。");
- //创建给字段命名的元组
- // 左边指定字段名称
- (int one, int two) tuple = (1, 2);
- WriteLine($"first:{tuple.one}, second:{tuple.two}");
- // 右边指定字段名称
- var tuple2 = (one: 1, two: 2);
- WriteLine($"first:{tuple2.one}, second:{tuple2.two}");
- // 左右两边同时指定字段名称
- (int one, int two) tuple3 = (first: 1, second: 2);
- /* 此处会有警告:由于目标类型(xx)已指定了其它名称,因为忽略元组名称xxx */
- WriteLine($"first:{tuple3.one}, second:{tuple3.two}");
6.3 解构
6.3.1解构元组
- var (one, two) = GetTuple();
- WriteLine($"first:{one}, second:{two}");
- static (int, int) GetTuple() {
- return (, );
- }
6.3.2解构可以应用于 .Net 的任意类型,
但需要编写 Deconstruct 方法成员(实例或扩展)
- public void Deconstruct(out type variable1, out type variable2...)
- public static void Deconstruct(this type instance, out type variable1, out type variable2...)
6.4 模式匹配
6.4.1 is 表达式(is expressions)
- static int GetSum(IEnumerable<object> values)
- {
- var sum = ;
- if (values == null) return sum;
- foreach (var item in values)
{- if (item is short) // C# 7 之前的 is expressions
- {
- sum += (short)item;
- }
- else if (item is int val) // C# 7 的 is expressions
- {
- sum += val;
- }
- else if (item is string str && int.TryParse(str, out var result))
- // is expressions 和 out variables 结合使用
- {
- sum += result;
- }
- else if (item is IEnumerable<object> subList)
- {
- sum += GetSum(subList);
- }
- }
- return sum;
- }
6.4.2 switch语句
- switch (item)
- {
- case type variable1:
- // processing...
- break;
- case type variable2 when predicate:
- // processing...
- break;
- default:
- // processing...
- break;
- }
6.5 Ref locals and returns
- static ref int GetLocalRef(int[,] arr, Func<int, bool> func)
- {
- for (int i = ; i < arr.GetLength(); i++)
- {
- for (int j = ; j < arr.GetLength(); j++)
- {
- if (func(arr[i, j]))
- {
- return ref arr[i, j];
- }
- }
- }
- throw new InvalidOperationException("Not found");
- }
- int[,] arr = { { , }, { , } };
- ref var num = ref GetLocalRef(arr, c => c == );
- num = ;
- Console.WriteLine(arr[, ]);
总结:虽然 C# 7 中提供了局部引用和引用返回,但为了防止滥用所以也有诸多约束,如:
1. 你不能将一个值分配给 ref 变量,如:
1 ref int num = 10; // error:无法使用值初始化按引用变量
2. 你不能返回一个生存期不超过方法作用域的变量引用,如:
1 public ref int GetLocalRef(int num) => ref num; // error: 无法按引用返回参数,因为它不是 ref 或 out 参数
3. ref 不能修饰 “属性” 和 “索引器”。
1 var list = new List<int>();2 ref var n = ref list.Count; // error: 属性或索引器不能作为 out 或 ref 参数传递
原理解析:非常简单就是指针传递,并且个人觉得此语法的使用场景非常有限,都是用来处理大对象的,目的是减少GC提高性能。
6.5 局部函数
- static IEnumerable<char> GetCharList(string str)
- {
- if (IsNullOrWhiteSpace(str))
- throw new ArgumentNullException(nameof(str));
- return GetList();
- IEnumerable<char> GetList()
- {
- for (int i = ; i < str.Length; i++)
- {
- yield return str[i];
- }
- }
- }
6.6. 扩展异步返回类型(Generalized async return types)
以前异步的返回类型必须是:Task、Task<T>、void,现在 C# 7 中新增了一种类型:ValueTask<T>,如下所示:
- public async ValueTask<int> Func()
- {
- await Task.Delay();
- return ;
- }
总结:ValueTask<T> 与 ValueTuple 非常相似,所以就不列举: ValueTask<T> 与 Task 之间的异同了,\但它们都是为了优化特定场景性能而
新增的类型。 使用 ValueTask<T> 则需要导入:
Install - Package System.Threading.Tasks.Extensions
6.7. 数字文本语法的改进(Numeric literal syntax improvements)
C# 7 还包含两个新特性:二进制文字、数字分隔符,如下所示:
- var one = 0b0001;
- var sixteen = 0b0001_0000;
- long salary = 1000_000_000;
- decimal pi = .141_592_653_589m;
注:二进制文本是以0b(零b)开头,字母不区分大小写;数字分隔符只有三个地方不能写:开头,结尾,小数点前后。
总结:二进制文本,数字分隔符 可使常量值更具可读性。
七、异步的优化
尽管如此,异步方法可以返回的内容是一些小改进,但是可以在某些情况下提供巨大的性能提升。 你不再需要返回一个Task,如果值已经可用, 这可以减少开销,使用async方法来创建Task对象。
八、总结
在这个介绍性章节中,您看到了一个简短而高级的摘要,与先前版本相比,.NET Core 2和ASP.NET Core 2众多变化。
现在,你也知道了.NET Standard 2及其用途。我们展示了C#6和C#7中可用的一些新功能的例子。
这些可能非常有用的是让你用更少的东西编写更多东西,并使你的代码更易读和更容易维护。
《ASP.NET Core 高性能系列》这是一本关于一般Web应用程序性能改进的文章,而且很多无视语言或框架的知识。
下一章中,您将了解性能如何重要,并了解崭新的新.NET Core开发栈, 我们还将看到可用的工具,并了解用图表展示硬件性能。
额外推荐Span Memory相关文章
https://www.cnblogs.com/uoyo/p/12207148.html
.net core中的System.Buffers名字空间
https://www.cnblogs.com/TianFang/p/9193881.html
《ASP.NET Core 高性能系列》致敬伟大的.NET斗士甲骨文!的更多相关文章
- 《ASP.NET Core 高性能系列》关于.NET Core的配置信息的若干事项
1.配置文件的相关闲话 Core自身对于配置文件不是必须品,但由上文分析可知ASP.NET Core默认采用appsettings.json作为配置文件,关于配置信息的优先等级 命令行>环境变量 ...
- 《ASP.NET Core 高性能系列》关于.NET Core的部署方式
概述,.NET Core应用程序可以创建三种类型的部署:FDD SCD FDE 框架依赖的部署(FDD).顾名思义,框架依赖的部署(FDD)依赖于目标系统上是否存在.NET Core版本.由于.NET ...
- 《ASP.NET Core 高性能系列》ASP.NET Core的启动过程(1)
一.一切从头开始 简述:知道事情的真相就应该从头 开始,下面我们代码先行 public class Program { public static void Main(string[] args) { ...
- 《ASP.NET Core 高性能系列》静态文件中间件
一.概述 静态文件(如 HTML.CSS.图片和 JavaScript等文件)是 Web程序直接提供给客户端的直接加载的文件. 较比于程序动态交互的代码而言,其实原理都一样(走Http协议), ASP ...
- 《ASP.NET Core 高性能系列》环境(EnvironmentName)的设置
一.概述 程序启动时Host捕获到环境相关数据,然后交由IEnvironment(传说要作废,但是觉得这个有设计点问题,因为.NET Core 非Web怎么处理?),然后交由IWebHostEnvir ...
- 《ASP.NET Core 高性能系列》关于性能的闲聊
一.通常的性能问题类型 让我们一起看看那些公共的性能问题,看看他们是或者不是.我们将了解到为什么我们常常在开发期间会错过这些问题.我们也会看看当我们考虑性能时语言的选择.延迟.带宽.计算等因素. 二. ...
- 《ASP.NET Core 高性能系列》Span<T>和Memory<T>
一.Span<T>概述 原文:Provides a type- and memory-safe representation of a contiguous region of arbit ...
- 跟我学: 使用 fireasy 搭建 asp.net core 项目系列之一 —— 开篇
==== 目录 ==== 跟我学: 使用 fireasy 搭建 asp.net core 项目系列之一 —— 开篇 跟我学: 使用 fireasy 搭建 asp.net core 项目系列之二 —— ...
- 跟我学: 使用 fireasy 搭建 asp.net core 项目系列之三 —— 配置
==== 目录 ==== 跟我学: 使用 fireasy 搭建 asp.net core 项目系列之一 —— 开篇 跟我学: 使用 fireasy 搭建 asp.net core 项目系列之二 —— ...
随机推荐
- WPF Dispatcher的使用
<Window x:Class="DispatcherExam.MainWindow" xmlns="http://schemas.micro ...
- requirejs教程(一):基本用法
介绍 RequireJS是一个非常小巧的JavaScript模块载入框架,是AMD规范最好的实现者之一.最新版本的RequireJS压缩后只有14K,堪称非常轻量.它还同时可以和其他的框架协同工作,使 ...
- javascript控制rem字体大小
摘要:在写响应式H5页面的时候,我常常会用rem字体,为了兼容多个分辨率的设备,需要写多个@media标签,太麻烦并且不够精致,尤其是移动端的页面往往达不到我想要的效果,后来就用js替代了css的@m ...
- QT的进程与线程(cmd /c的写法)
该文章原创于Qter开源社区(www.qter.org),作者yafeilinux,转载请注明出处! 导语 在前面的几节内容中讲解了Qt网络编程的一些基本内容,这一节来看一下在Qt中进程和线程的基本应 ...
- Win10《芒果TV》更新v3.4.10春光版:优化弹窗体验,修复热键和推送
春来触地故乡情,忽见风光忆两京,金谷踏花香骑入,曲江碾草钿车行,Win10版<芒果TV>更新v3.4.10,进一步优化弹窗体验,修复热键和推送异常. Win10版<芒果TV>V ...
- SQLite Expert Professional 打开加密SQLite数据库
原文 SQLite Expert Professional 打开加密数据库 (已修改) 版本:sqlite expert professional 4.2.0.739 (x86) 目的:用SQLite ...
- PostgreSQL在win7上安装详细步骤
原文:PostgreSQL在win7上安装详细步骤 PostgreSQL安装: 一.windows下安装过程 安装介质:postgresql-9.1.3-1-windows.exe(46M),安装过程 ...
- Attention is all you need及其在TTS中的应用Close to Human Quality TTS with Transformer和BERT
论文地址:Attention is you need 序列编码 深度学习做NLP的方法,基本都是先将句子分词,然后每个词转化为对应的的词向量序列,每个句子都对应的是一个矩阵\(X=(x_1,x_2,. ...
- Delphi事件的广播
原文地址:Delphi事件的广播 转作者:MondaySoftware 明天就是五一节了,辛苦了好几个月,借此机会应该尽情放松一番.可是想到Blog好久没有写文章,似乎缺些什么似的.这几个月来在项目中 ...
- 我们检测到您的浏览器不兼容传输层安全协议 (TLS) 1.1 或更高版本,此协议在 Internet 上用于确保您通信的安全性。
早上使用.Net WebClient类采集亚马逊数据,返回http 400 Bad Request错误,内容里面有“我们检测到您的浏览器不兼容传输层安全协议 (TLS) 1.1 或更高版本,此协议在 ...