.net core 2.1的重头戏就是性能,其中最重要的两个类就是span和memory,本文这里简单的介绍一下这两个类的使用。

什么是 Span<T>

Span<T> 是新一种新值类型。它表示一段连续的区域,它通常和数组关联,表示数组中的一部分内存。

var        arr   = new byte[10];
Span<byte> bytes = arr;

也可以取数组中的一部分:

var bytes = new Span<byte>(arr, 3, 5);

初一乍看,span<T>和ArraySegment<T>非常类似,但span更加强大得多,它不但能用于分离数组,还可以引用栈上的数据。

Span<byte> bytes = stackalloc byte[2];

也可以引用指针数据,

Span<byte> bytes;
unsafe { bytes = new Span<byte>((byte*)ptr, 1); }

另外,span还支持 reinterpret_cast 的理念,即可以将 Span<byte> 强制转换为 Span<int>,配合MemoryMarshal类使用,span<T>大多数的时候都可以代替指针了。

除了功能更加强大外,span在bcl库中也得到了更多的支持,大多数支持数组的函数现在基本上都能直接支持span了,如:

var inputSpan = input.AsSpan();
int first     = int.Parse(inputSpan.Slice(3, 5));

这个函数中,int.Parse函数就能直接支持span,并且由于不产生子字符串,比使用substring的方法性能更高。

另外,系统也支持数组类型到span的隐式转换,同时提供了AsSpan的显示扩展方法,方便将数组类型转换为span。

除了功能强大外,span的性能也是非常高的,对span的操作基本上和访问数组一样高,无需通过计算来确定指针开头及其起始偏移,因为"引用"字段本身已对两者进行了封装。相比之下,ArraySegment<T> 有单独的偏移字段,这就增加了索引编制和数据传递操作的成本。

什么是 Memory<T>

Span<T>虽然强大而好用,但它只能存在于栈上,而不能存在于堆上,原因主要有如下两点:

  1. span包含"引用"字段(如数组的开头),这些引用被称为"内部指针"。对于 .NET 运行时的垃圾回收器,跟踪这些指针是一项成本相对高昂的操作。因此,运行时将这些引用约束为仅存在于堆栈上,因为它隐式规定了可以存在的内部指针数量下限。
  2. 对 Span 执行的读取和写入操作不是原子操作。如果多个线程同时对 Span 在堆上的字段执行读取和写入操作,存在"撕裂"风险。

这个限制决定了无法将 Span 装箱,进而无法将 Span<T> 与现有反射调用 API结合使用,也无法作为泛型参数。

对于大部分同步处理功能,这个并没有太大的影响,但由于span<T>无法存储到堆,从而导致其无法在异步上下文中使用。为了解决这个问题,.net引入了一个新类型Memory<T>。

Memory和span的使用方法大同小异,

var arr   = new byte[10];
var bytes = new Memory<byte>(arr, 3, 5);

不同之处在于 Memory<T> 是不类似引用的结构,可以存在于堆上。.net bcl库对memory也做了很好的支持,如Stream.ReadAsync就能直接支持memory<byte>作为参数。

另外,也可以从Memory的Span属性创建指向该Memory的span,这样也可以使用span的强大的功能。

参考文章:

C# - Span 全面介绍:探索 .NET 新增的重要组成部分

.net下的span和memory的更多相关文章

  1. System.Span, System.Memory,还有System.IO.Pipelines

    System.Span, System.Memory,还有System.IO.Pipelines 使用高性能Pipelines构建.NET通讯程序 .NET Standard支持一组新的API,Sys ...

  2. linux 下tomcat出现 Native memory allocation (malloc) failed to allocate 1915224064 bytes for committing reserved memory问题

    ## There is insufficient memory for the Java Runtime Environment to continue.# Native memory allocat ...

  3. C++库研究笔记——Linux下是否需要使用memory pool?

    Linux Slab分配器(一)--概述 Linux slab 分配器剖析 C++库研究笔记——内存池实现 做了一些测试:发现linux使用内存池与否没有明显差别,仅仅有2倍. Linux内存处理机制 ...

  4. Js/如何操作div下面的span元素或者是img之类的标签元素

    $("div[name='MatTypeName']").click(function (e) { $("div[name='MatTypeName']").e ...

  5. vue中用v-for循环出出来的div下面的span不给宽度也能相对于div居中

    效果图 1.html <div> <div v-on:mousemove="dataDetails($event, item)" v-on:mouseleave= ...

  6. 《ASP.NET Core 高性能系列》Span<T>和Memory<T>

    一.Span<T>概述 原文:Provides a type- and memory-safe representation of a contiguous region of arbit ...

  7. 内存包装类 Memory 和 Span 相关类型

    1. 前言 2. 简介 3. Memory<T>和Span<T>使用准则 3.1. 所有者, 消费者和生命周期管理 3.2. Memory<T> 和所有者/消费者模 ...

  8. 在 C# 中使用 Span<T> 和 Memory<T> 编写高性能代码

    目录 在 C# 中使用 Span 和 Memory 编写高性能代码 .NET 中支持的内存类型 .NET Core 2.1 中新增的类型 访问连续内存: Span 和 Memory Span 介绍 C ...

  9. Label下FormattedText中的Span无法使用Binding的解决方法

    在Xamarin.Forms中,Xaml的模板功能并没有原生WPF丰富,比如Label中虽然有FormattedText可以添加Span来丰富Label的功能,但是下面的Span中的Text并没有绑定 ...

随机推荐

  1. 训练赛第二场E题 Cottage Village

    题目大意:在一条X轴上,有若干个正方形,并且保证这些正方形的中心都在X轴上,然后输入n个正方形的中心的X坐标,和正方形的边长,现在要再插入一个正方形,要求是,新插入的正方形至少要有一条边与原来的正方形 ...

  2. python中的 __repr__和__str__

    __repr__,被内置函数repr用于把一个对象用"官方"的字符串形式表示出来(终端友好)    1.值传给eval()来返回一个对象的字符串表示形式    2.否则返回一个尖括 ...

  3. G. (Zero XOR Subset)-less(线性基)

    题目链接:http://codeforces.com/contest/1101/problem/G 题目大意:给你n个数,然后让你把这n个数分成尽可能多的集合,要求,每个集合的值看做这个集合所有元素的 ...

  4. Javascript - 表达式与语句

    表达式与语句(Expression&Statement) 流程控制语句 1.嵌入式语句 嵌入式即这种语句可以无限嵌套N层.所有嵌入式语句只需要键入首个关键单词,在visual studio里按 ...

  5. Mybatis逆向工程——(十四)

    逆向工程可以快速将数据库的表生成JavaBean,同时生成对单标操作的Mapper.java与Mapper.xml,极大地提高了开发速度. 1.jar包

  6. retrying模块的学习

    retrying模块的学习 我们在写爬虫的过程中,经常遇到爬取失败的情况,这个时候我们一般会通过try块去进行重试,但是每次都写那么一堆try块,真的是太麻烦,所以今天就来说一个比较pythonic的 ...

  7. casper Dom的操作

    phantom.casperTest = true; phantom.outputEncoding="utf-8"; var casper = require('casper'). ...

  8. ckeditor:新增时会得到上次编辑的内容

    参考网址:http://blog.sina.com.cn/s/blog_6961ba9b0102wwye.html 第一次新增时没有问题,编辑器里面内容为空,编辑数据时,也是正常,但是第二次点击新增时 ...

  9. appium无ID、name定位处理【转】

    1.关于没有name,没有ID的元素的定位---通用篇解题思路:因为没有name,id:其实剩下的选择已不多,要么xpath,要么className.xpath木有好印象(稳定性不高,加之1.0x后需 ...

  10. day22-23作业

    1.字节流  字符流    2.read()  3.-1  4.System.out  5.InputStream  6.OutputStream 1.IO流按流向分为输入流和输出流,即输入流和输出流 ...