系列介绍

简介

【五分钟的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的更多相关文章

  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. spring security自定义指南

    序 本文主要研究一下几种自定义spring security的方式 主要方式 自定义UserDetailsService 自定义passwordEncoder 自定义filter 自定义Authent ...

  2. 2018-9-3-C#-const-和-readonly-有什么区别

    title author date CreateTime categories C# const 和 readonly 有什么区别 lindexi 2018-9-3 16:52:7 +0800 201 ...

  3. printk函数 用查询来调试

    前面一节描述了 printk 是任何工作的以及怎样使用它. 没有谈到的是它的缺点. 大量使用 printk 能够显著地拖慢系统, 即便你降低 cosole_loglevel 来避免加载控制 台设备, ...

  4. CF1151FSonya and Informatics

    CF1151FSonya and Informatics 给一个长度为 n$ (n\leq 100)$的 \(0/1\) 串,进行 k\((k \leq 10^9)\)次操作,每次操作选择两个位置 \ ...

  5. 2019-2-11-WPF-列表自动换行

    title author date CreateTime categories WPF 列表自动换行 lindexi 2019-02-11 08:55:31 +0800 2019-02-11 08:5 ...

  6. gulp 批量添加类名 在一个任务中使用多个文件来源

    1.首先安装环境 1.安装gulp: npm install gulp 2.安装gulp-clean-css npm install gulp-clean-css 3.安装gulp-css-wrap ...

  7. dotnet 删除只读文件

    如果直接通过 File.Delete 删除只读文件会出现没有权限提示,可以先设置文件不是只读然后删除文件 try { File.Delete(file); } catch (UnauthorizedA ...

  8. presto,dremio,spark-sql与ranger的整合记录

    dremio,spark-sql,presto和ranger的整合 当前,ranger没有现成的插件来管理dremio,spark-sql,presto. 暂时使用的方法是新建一个用户,如presto ...

  9. 设计模式2——状态模式State

    参考链接: 设计模式之状态模式:https://www.cnblogs.com/haoerlv/p/7777789.html 设计模式系列之状态模式:https://www.jianshu.com/p ...

  10. Excel数据处理

    合并计算: 数据面板下的合并计算 然后设置好合并计算的区域 以及勾选 首行跟最左列