系列介绍

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

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

正文

在上一篇文章:《闪电光速拳? .NetCore 中的Span》 中我们提到了在.net core 2.x 所新增的一个类型:Span

它与咱们传统使用的基础类型相比具有超高的性能,原因是它减少了大量的内存分配和数据量复制,并且它所分配的数据内存是连续的。

但是您会发现它无法用在我们项目的某些地方,它独特的 ref结构 使它没有办法跨线程使用、更没有办法使用Lambda表达式。

特别是在AspNetCore中,咱们会使用到大量的异步操作方法。“所以,这个时候如果我们又想跨线程操作数据又想获得类似Span这样的性能怎么办呢?” 上一篇文章我们留下了这样的一个问题,所以现在就是到了还愿的时候了。它就是与Span一起发布的孪生兄弟: Memory

狮子座和射手座黄金圣斗士同样具备超越光速的能力

什么是Memory

那什么是Memory呢?不妨我们先来猜测一下,它的结构是什么样子。毕竟它是Span的孪生兄弟,而Span的结构我们在前面就了解过了:

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(); //.....
}

当时我们说Span有各种缺陷的原因是由于它独特的 ref struct 关键字所导致的,导致它无法拆箱装箱、无法书写Lambda、无法跨线程等。但是它兄弟却可以克服缺点,所以我们想想它会和Span在声明上有哪些差距呢? 是的,您可能已经想到了:它不会有 ref 关键字了。

所以,我们看到它的内部结构就是酱紫的:

public readonly struct Memory<T>
{
public static Memory<T> Empty { get; }
public bool IsEmpty { get; }
public int Length { get; }
public Span<T> Span { get; }
public void CopyTo([NullableAttribute(new[] { 0, 1 })] Memory<T> destination);
public MemoryHandle Pin();
public Memory<T> Slice(int start, int length);
public T[] ToArray();
public override string ToString();
}

和我们猜想的一样。它少了ref关键字,内部方法也和Span差不多(同样拥有CopyTo,Slice等),但是还是有一些差异,比如多了Pin方法,Span属性等。

被声明为ref struct的结构,叫做“ByRefLike”。所以在我们在进行反射的时候,我们使用Type会看到有这样一个属性:IsByRefLike

好像有点超纲了哈(>人<;)

按照MSDN给出的解释:

该结构是使用中的C# ref struct 关键字声明的。 不能将类似 byref 的结构的实例放置在托管堆上。

所以这也是为什么上一篇文章说的:Span只能放置在内存栈中的原因。

那么反过来想,没有了ref关键字之后。Memory是不是就可以放置在托管堆上了呢?是不是就可以进行拆装箱,克隆副本供其它线程的内存栈使用了呢? 好吧,可能是这样。所以这也许就是它能够被允许跨线程使用的原因吧。

进行到了这一步,那我们再回过头来想想Memory是什么呢? 其实现在我们心里其实都已经有个底了:

与 Span<T>一样,Memory<T> 表示内存的连续区域。 但 Span<T>不同,Memory<T> 不是ref 结构。 这意味着 Memory<T> 可以放置在托管堆上,而 Span<T> 不能。 因此,Memory<T> 结构与 Span<T> 实例没有相同的限制。 具体而言:

  • 它可用作类中的字段。
  • 它可跨 await 和 yield 边界使用。

除了 Memory<T>之外,还可以使用 System.ReadOnlyMemory<T> 来表示不可变或只读内存。

这是MSDN给出来的解释,不是我乱编的哈

【5min+】传说中的孪生兄弟? Memory and Span的更多相关文章

  1. 阿里云产品介绍(二):云服务器ECS的孪生兄弟们

    上一篇介绍的云服务器ECS,是阿里云最基础的产品,也是每一个云计算厂商最基础的产品,俗称爆款.除了标准的云服务器,阿里云也不停的在推出面向特殊业务场地的云服务器,可以说是ECS的孪生兄弟们. 这一篇就 ...

  2. Android图表库MPAndroidChart(十)——散点图的孪生兄弟气泡图

    Android图表库MPAndroidChart(十)--散点图的孪生兄弟气泡图 起泡图和散点图如出一辙,但是个人认为要比散点图好看一点,我们来看下实际的演示效果 这个和散点图的实现很相似,我们一起来 ...

  3. [译]C# 7系列,Part 10: Span<T> and universal memory management Span<T>和统一内存管理

    原文:https://blogs.msdn.microsoft.com/mazhou/2018/03/25/c-7-series-part-10-spant-and-universal-memory- ...

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

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

  5. 深入理解计算机系统(4.1)---X86的孪生兄弟,Y86指令体系结构

    引言 各位猿友们好,计算机系统系列很久没更新了,实在是抱歉之极.新的一年,为了给计算机系统系列添加一些新的元素,LZ将其更改为书的原名<深入理解计算机系统>.这本书非常厚,而且难度较高,L ...

  6. grep与孪生兄弟egrep差异

    egrep是对grep的功能扩展,让其支持正则更加完美! #grep与egrep不同  egrep完全支持正则 ls |grep -i '[a-z]\{3\}'    === ls |egrep -i ...

  7. SpringMVC的孪生兄弟WebFlux

    一.入门文字介绍 官方口水话简短翻译: Spring WebFlux是一个非阻塞的Web框架,用于利用多核,短时间可一处理大量并发连接. 非阻塞式 在servlet3.1提供了非阻塞的API,WebF ...

  8. .net下的span和memory

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

  9. 【C# IO 操作 】内存包装类 Memory <T>和 Span<T> 相关类型

    简介 .NET 包含多个相互关联的类型,它们表示任意内存的连续的强类型区域. 这些方法包括: System.Span<T> 用于访问连续的内存区域 得到该类型的实例: 1个T类型的数组 1 ...

随机推荐

  1. 模板——BigInteger

    #include <iostream> #include <cstring> #include <string> #include <vector> # ...

  2. 2018-4-29-C#-将dll打包到程序中

    title author date CreateTime categories C# 将dll打包到程序中 lindexi 2018-04-29 09:43:22 +0800 2018-2-13 17 ...

  3. P1074 彩票摇奖

    题目描述 为了丰富人民群众的生活.支持某些社会公益事业,北塔市设置了一项彩票.该彩票的规则是: (1) 每张彩票上印有 7 个各不相同的号码,且这些号码的取指范围为 1~33. (2) 每次在兑奖前都 ...

  4. 一个基于 Slab 缓存的 scull: scullc

    是时候给个例子了. scullc 是一个简化的 scull 模块的版本, 它只实现空设备 -- 永久 的内存区. 不象 scull, 它使用 kmalloc, scullc 使用内存缓存. 量子的大小 ...

  5. Linux 内核kobject非 缺省属性

    在许多情况中, kobject 类型的 default_attrs 成员描述所有的 kobject 会拥有的属性. 但是那不是一个设计中的限制; 属性随意可以添加到和删除自 kojects. 如果你想 ...

  6. mysql修改数据库密码

    方法1: 运行MySQL 5.7 Command Line Client,输入老的密码: use mysql: update user set authentication_string=passwo ...

  7. 2018-2-13-win10-uwp-模拟网页输入

    title author date CreateTime categories win10 uwp 模拟网页输入 lindexi 2018-2-13 17:23:3 +0800 2018-2-13 1 ...

  8. TypeScript躬行记(7)——命名空间

    TypeScript中的命名空间可将那些具有内在联系的接口.类或对象等代码组织在一起,既能隔离作用域,也能避免命名冲突,并且使得代码结构清晰,更易追踪.在命名空间内部,所有实体部分默认都是私有的,需要 ...

  9. Kafka学习笔记4--Kafka消费者的客户端(PHP)开发

    一.准备工作 虽然 Kafka 是用 Java/Scala 语言编写的,但这不妨碍它对多语言的支持.可以在 Kafka 官网的 CLIENTS 查看 Kafka 支持的语言,其中包括 C/C++.Py ...

  10. lua字符串分割函数[适配中文特殊符号混合]

    lua的官方函数里无字符串分割,起初写了个简单的,随之发现如果是中文.字符串.特殊符号就会出现分割错误的情况,所以就有了这个zsplit. function zsplit(strn, chars) f ...