系列介绍

简介

【五分钟的DotNet】是一个利用您的碎片化时间来学习和丰富.net知识的博文系列。它所包含了.net体系中可能会涉及到的方方面面,比如C#的小细节,AspnetCore,微服务中的.net知识等等。

5min+不是超过5分钟的意思,"+"是知识的增加。so,它是让您花费5分钟以下的时间来提升您的知识储备量。

正文

在dotnet core2.x之后,引入了一个叫做Span<T>的类型。如果您的项目已经升级到了新版的dotnet core 以及使用C# 7+。您会发现我们曾经使用的许许多多类型都增加了一个扩展方法“AsSpan()”。在Vs中小手一点就会出现:


  1. var s = ("xxx").AsSpan();
  2. var s1 = new byte[10].AsSpan();
  3. //.......more

那么这个家伙到底是个什么东西?怎么用呢?

先来扒一扒它的内部方法:

  1. public readonly ref struct Span<T>
  2. {
  3. public void Clear();
  4. public void CopyTo([NullableAttribute(new[] { 0, 1 })] Span<T> destination);
  5. public void Fill(T value);
  6. public Enumerator GetEnumerator();
  7. public Span<T> Slice(int start, int length);
  8. public T[] ToArray();
  9. public override string ToString();
  10. //.....
  11. }

这里只展示它部分的方法,但是关键的一点我们可以看到:它是一个结构性(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的更多相关文章

  1. .NetCore中的日志(2)集成第三方日志工具

    .NetCore中的日志(2)集成第三方日志工具 0x00 在.NetCore的Logging组件中集成NLog 上一篇讨论了.NetCore中日志框架的结构,这一篇讨论一下.NetCore的Logg ...

  2. .NetCore中的日志(1)日志组件解析

    .NetCore中的日志(1)日志组件解析 0x00 问题的产生 日志记录功能在开发中很常用,可以记录程序运行的细节,也可以记录用户的行为.在之前开发时我一般都是用自己写的小工具来记录日志,输出目标包 ...

  3. AutoMapper在asp.netcore中的使用

    # AutoMapper在asp.netcore中的使用  automapper 是.net 项目中针对模型之间转换映射的一个很好用的工具,不仅提高了开发的效率还使代码更加简洁,当然也是开源的,htt ...

  4. netcore中的缓存介绍

    Cache(缓存)是优化web应用的常用方法,缓存存放在服务端的内存中,被所有用户共享.由于Cache存放在服务器的内存中,所以用户获取缓存资源的速度远比从服务器硬盘中获取快,但是从资源占有的角度考虑 ...

  5. 在netcore中如何注入同一个接口的多个实现

    netcore中自带了Ioc框架,这也影响了我们的编码习惯,以前都是静态类或者直接new对象,现在有了Ioc框架的支持,我们也不必守旧,应当使用起来,接受这种对象管理方式.使用过java的同仁,都习惯 ...

  6. .NetCore中EFCore的使用整理(二)-关联表查询

    EF常用处理关联加载的方式有3中:延迟加载(Lazy Loading).贪婪加载 (Eager Loading)以及显示加载. 一.EF Core  1.1 1.当前的版本,还不支持延迟加载(Lazy ...

  7. .NetCore中EFCore for MySql整理(三)之Pomelo.EntityFrameworkCore.MySql

    一.Pomelo.EntityFrameworkCore.MySql简介 Git源代码地址:https://github.com/PomeloFoundation/Pomelo.EntityFrame ...

  8. .NetCore中如何实现权限控制 基于Claim角色、策略、基于Claim功能点处理

    .NetCore中如果实现权限控制的问题,当我们访问到一个Action操作的时候,我们需要进行权限控制 基于claims 角色控制 基于角色控制总觉得范围有点过大,而且控制起来感觉也不是太好,举一个例 ...

  9. .NetCore中EFCore for MySql整理(二)

    一.简介 EF Core for MySql的官方版本MySql.Data.EntityFrameworkCore 目前正是版已经可用当前版本v6.10,对于以前的预览版参考:http://www.c ...

随机推荐

  1. python3在pycharm中为什么导入random模块不能用? TypeError: 'module' object is not callable

    新手学python求大神指导,也用sys导入了random.py的路径,仍然不行. 刚刚排错貌似找到了问题的原因...那是因为我在pycharm中新建的python文件名就是random,所以当前目录 ...

  2. (二)Centos7下Yum更新安装PHP5.5,5.6,7.0

    yum源默认的版本太低了,手动安装有一些麻烦,想采用Yum更新安装的可以使用下面的方案: 1.检查当前安装的PHP包 yum list installed | grep php 如果有安装的PHP包, ...

  3. 2019-10-19-dotnet-给MatterMost订阅RSS博客

    title author date CreateTime categories dotnet 给MatterMost订阅RSS博客 lindexi 2019-10-19 08:12:36 +0800 ...

  4. 总结thinkphp快捷查询getBy、getField、getFieldBy用法及场景

    thinkphp作为国内现阶段最成熟的框架:没有之一: 不得不说是有好些特别方便的方法的: 然而如果初接触thinkphp的时候难免会被搞的有点迷茫: for example这些: getBy get ...

  5. 基于小米即时消息云服务(MIMC)的Web IM

    michat 一个基于小米即时消息云服务(MIMC)的Web IM. 源码地址github和gitee同步. 截图展示 如何使用 请先双击目录"需要安装的jars"的install ...

  6. es6笔记 day3---Promise

    作用:解决异步回调问题 先知道它的大概语法就好了,这个东西需要平时用到才知道它的用处 语法: let promise= new Promise(function(resolve,reject){ // ...

  7. <数论相关>欧几里得与拓展欧几里得证明及应用

    欧几里得算法 欧几里得算法的复杂度为O(log(n)),是一个非常高效的求最大公约数算法. 在这里不证明欧几里得算法的复杂度,有兴趣的可以访问以下链接:http://blog.sina.com.cn/ ...

  8. [竞赛]Beat Matching(对拍)

    对拍的基本理论这里恕我不一一叙述,不会的请转身到这里:http://blog.csdn.net/code12hour/article/details/51252457 分为以下几个部分: 1.暴力伪标 ...

  9. 分析CPU使用率不断增加的原因

    工程中发现引起的问题: 结合别的朋友的意见,我的优化思路是: 1.排查是否内存泄漏 经过反复查询代码,未发现有内存泄漏(可以自己百度搜索C#内存泄漏的原因).可以通过任务管理器分析是否有内存泄漏,打开 ...

  10. 从零开始のcocos2dx生活(六)EventDispatcher

    EventDispatcher可能是所有的里面比较不容易理解也不容易看的 我说自己的理解可能会误导到你们-[索了你们看不下去>< 我写了几乎所有的代码的注释,有的是废话跳过就好 主要的代码 ...