【5min+】闪电光速拳? .NetCore 中的Span
系列介绍
简介
【五分钟的DotNet】是一个利用您的碎片化时间来学习和丰富.net知识的博文系列。它所包含了.net体系中可能会涉及到的方方面面,比如C#的小细节,AspnetCore,微服务中的.net知识等等。
5min+不是超过5分钟的意思,"+"是知识的增加。so,它是让您花费5分钟以下的时间来提升您的知识储备量。
正文
在dotnet core2.x之后,引入了一个叫做Span<T>的类型。如果您的项目已经升级到了新版的dotnet core 以及使用C# 7+。您会发现我们曾经使用的许许多多类型都增加了一个扩展方法“AsSpan()”。在Vs中小手一点就会出现:
var s = ("xxx").AsSpan();
var s1 = new byte[10].AsSpan();
//.......more
那么这个家伙到底是个什么东西?怎么用呢?
先来扒一扒它的内部方法:
public readonly ref struct Span<T>
{
public void Clear();
public void CopyTo([NullableAttribute(new[] { 0, 1 })] Span<T> destination);
public void Fill(T value);
public Enumerator GetEnumerator();
public Span<T> Slice(int start, int length);
public T[] ToArray();
public override string ToString();
//.....
}
这里只展示它部分的方法,但是关键的一点我们可以看到:它是一个结构性(struct 关键字)。
而且!!而且!!! 你没看错,它还加了一个ref关键字。
所以按照我们在上一篇文章中介绍过的 .net中的栈和堆,我们猜想这种结构类型的数据应该是存放在内存栈中,具有很快的访问速度。而且它拥有了ref关键字,证明它具有ref结构体的特点:
- 不能对 ref struct 装箱
- ref struct 类型不能实现接口
- 不能将 ref struct 声明为类或常规结构的字段成员
- 不能声明异步方法中属于 ref struct 类型的本地变量
- 无法在迭代器中声明 ref struct 本地变量
- 无法捕获 Lambda 表达式或本地函数中的 ref struct 变量
而且根据它公开的这些方法,我们会发现它有点类似我们常用的几个基础类型:string 、 byte[] ……。
所以直觉告诉我们,它应该是一个拿来存放数据的类型。
so,来看看MSDN - Magazine中它的解释:
System.Span<T> 是在 .NET 中发挥关键作用的新值类型。使用它,可以表示任意内存的相邻区域,无论相应内存是与托管对象相关联,还是通过互操作由本机代码提供,亦或是位于堆栈上。除了具有上述用途外,它仍能确保安全访问和高性能特性,就像数组一样。
果不其然,和我们猜想的一样。那么它出现的意义是什么呢? 性能!!!!
而且是超级快的性能。大家都知道以往如果我们想提高数据间的操作效率(比如数据偏移、裁剪等),就只能使用指针来操作内存中的数据。这样虽然一波操作猛如虎,但是写起来费劲不说,我们还得将传统的C#代码设置为不安全代码,除了添加unsafe关键字之外还需要打开项目中执行不安全代码的选项。
所以,有没有办法既不操作指针而又有高性能呢? 好吧,Span大爷来了。
Span在C# 7.x中被引入,所以它的年龄还算比较小,也是因为这些原因。以往的项目可能没有办法使用它。
它到底有多快
大家一般都是想直接看东西,所以我写了一份对比的代码。功能很简单,都是截取字符串中的一部分代码,并且进行多次的循环操作。
执行结果我都惊呆了:
是的,您没有看错。差距不是一般的大。
其实刚开始我以为Span并没有什么作用,因为我将数据源(图中的compareStr)仅仅设置为了几个单词。然后对他们进行了1亿的循环操作,但是最后的结果只有很小的差距,不到百分之30。
后来我想了一下,应该让数据更贴近现实,于是就将一张图片转换为base64然后作为数据源。结果惊呆了,差了接近百倍。而且随着循环次数和对数据源的操作次数的增多,Span和传统字符串之间的性能差距更大。
传说中的闪电光速拳到底有多快呢
它为什么这么快
它与传统的string操作比起来为什么会具有这么快的速度呢? 按照我们之前的一些猜想和msdn所给出的一点信息,我们可以得到以下的结论:
- 它分配堆栈上而不是在托管堆。
- 它所创建的数据是内存连续的,因此具有更快的遍历速度。
这些特点和string等原有类型比起来就非常的具有优势了:原来对string操作涉及到大量的字符串分配和内存复制。所以当操作的数据量小的时候还好,但是随着操作次数和处理数据量的增加之后,这是非常消耗性能的。
Span会给我们带来什么
那么,既然它拥有如此高的性能,那么我们该在什么地方使用它呢?
这很简单,如果您以前有对大量字符串进行截取或者处理的地方,一般都可以替换为Span。(为什么是一般呢
【5min+】闪电光速拳? .NetCore 中的Span的更多相关文章
- .NetCore中的日志(2)集成第三方日志工具
.NetCore中的日志(2)集成第三方日志工具 0x00 在.NetCore的Logging组件中集成NLog 上一篇讨论了.NetCore中日志框架的结构,这一篇讨论一下.NetCore的Logg ...
- .NetCore中的日志(1)日志组件解析
.NetCore中的日志(1)日志组件解析 0x00 问题的产生 日志记录功能在开发中很常用,可以记录程序运行的细节,也可以记录用户的行为.在之前开发时我一般都是用自己写的小工具来记录日志,输出目标包 ...
- AutoMapper在asp.netcore中的使用
# AutoMapper在asp.netcore中的使用 automapper 是.net 项目中针对模型之间转换映射的一个很好用的工具,不仅提高了开发的效率还使代码更加简洁,当然也是开源的,htt ...
- netcore中的缓存介绍
Cache(缓存)是优化web应用的常用方法,缓存存放在服务端的内存中,被所有用户共享.由于Cache存放在服务器的内存中,所以用户获取缓存资源的速度远比从服务器硬盘中获取快,但是从资源占有的角度考虑 ...
- 在netcore中如何注入同一个接口的多个实现
netcore中自带了Ioc框架,这也影响了我们的编码习惯,以前都是静态类或者直接new对象,现在有了Ioc框架的支持,我们也不必守旧,应当使用起来,接受这种对象管理方式.使用过java的同仁,都习惯 ...
- .NetCore中EFCore的使用整理(二)-关联表查询
EF常用处理关联加载的方式有3中:延迟加载(Lazy Loading).贪婪加载 (Eager Loading)以及显示加载. 一.EF Core 1.1 1.当前的版本,还不支持延迟加载(Lazy ...
- .NetCore中EFCore for MySql整理(三)之Pomelo.EntityFrameworkCore.MySql
一.Pomelo.EntityFrameworkCore.MySql简介 Git源代码地址:https://github.com/PomeloFoundation/Pomelo.EntityFrame ...
- .NetCore中如何实现权限控制 基于Claim角色、策略、基于Claim功能点处理
.NetCore中如果实现权限控制的问题,当我们访问到一个Action操作的时候,我们需要进行权限控制 基于claims 角色控制 基于角色控制总觉得范围有点过大,而且控制起来感觉也不是太好,举一个例 ...
- .NetCore中EFCore for MySql整理(二)
一.简介 EF Core for MySql的官方版本MySql.Data.EntityFrameworkCore 目前正是版已经可用当前版本v6.10,对于以前的预览版参考:http://www.c ...
随机推荐
- vector容器、
一. vector 向量容器1. 创建 vector 对象(1)不指定容器大小vector<int> V;(2)指定容器大小vector<int> V(10);(3) ...
- hibernate中因双向依赖而造成的json怪相--springmvc项目
简单说一下Jackson 如果想要详细了解一下Jackson,可以去其github上的项目主页查看其版本情况以及各项功能.除此以外,需要格外提一下Jackson的版本问题.Jackson目前主流版本有 ...
- element-ui—dialog使用过程中的坑
场景一:我们将dialog写成一个可复用的公共组件用于显示不同内容(如表格操作中的修改或添加的弹窗),之后发现dialog的遮罩将弹出层(点击修改或添加后理应由一个弹窗显示出来)都盖住了,而我想要的效 ...
- 2018-8-10-win10-uwp-slider-隐藏显示数值
title author date CreateTime categories win10 uwp slider 隐藏显示数值 lindexi 2018-08-10 19:17:19 +0800 20 ...
- Roslyn 使用 Directory.Build.props 管理多个项目配置
在一些大项目需要很多独立的仓库来做,每个仓库之间都会有很多相同的配置,本文告诉大家如何通过 Directory.Build.props 管理多个项目配置 在我的 MVVM 框架需要三个不同的库,一个是 ...
- Junit测试代码时出现initializationError 错误
首先代码没有错误,执行Junit测试时出现以上错误.上网查资料发现少了包 从网上下载了一个jar包解决了hamcrest-core-1.3.jar 现在下载包搜索的好多坑,有的网站必须注册才能下载,而 ...
- PHP判断类型
is_bool();//判断是否为布尔型 is_float(); //判断是否为浮点型 is_int(); //判断是否为整型 is_numeric(); //判断是否为数值型 is_ ...
- vue的filters过滤器的使用
举个例子,过滤后台转过来的时间格式2019-08-29T02:15:08.000+0000转换为2019-08-29T02:15:08 html部分 <span v-if="item. ...
- hdu 6852Path6(最短路+最小割)
传送门 •题意 有n个城市,标号1-n 现花费最小的代价堵路 使得从1号城市到n号城市的路径边长 (注意只是变长不是最长) 堵一条路的代价是这条路的权值 •思路 在堵路以前,从1到n的最小路径当然是最 ...
- Channel 9视频整理【3】
Will 保哥 微软mvp https://channel9.msdn.com/Niners/Will_Huang 繁体中文视频 Visual Studio 2017 新功能探索 https://ch ...