6

Dotnet中Span, Memory和ReadOnlySequence之浅见

 3 years ago
source link: https://mp.weixin.qq.com/s?__biz=MjM5MjQwMDUzMw%3D%3D&%3Bmid=2247484247&%3Bidx=1&%3Bsn=8f10ebb9c9768743e32fec627455ee2f
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

过年啦,写个短点的。同时,提前给大家拜个年。

总有小伙伴们跑过来讨论关于Span和Memory的使用,眼瞅是最近关于Span的文章有点多,看飞了。

今天写这个,就是往回拉一拉。

写之前,先声明一下。这些内容是我自己使用的一些经验,并不代表这些类的全部内容就是这些,只是说,我是这么用的,而且用得很好。

1. Span

Span在我的概念中,就是一个快速的同步访问器。

就这么简单。

Span很快。在我前边关于Span的文章中分析过,可以移步【传送门】去看。而且,它与foreach一起使用也很快,主要是因为Span的GetEnumerator使用了引用返回。

你看,Span本身就被设计成了一个非常快的东西。

同时,Span是同步的。也就是说,它没有提供任何异步的方法和属性。

说到为什么Span是同步的,这倒是一个问题。我们需要从根上来找找。Span背后的连续内存块,主要来自于以下几个方面:

  • 数组的切片

  • Memory

  • 非托管指针 void*

  • stackalloc

其中,第一个是堆上分配的数组的一部分。第二个是基于连续内存的。第三个非托管 void* 本身就是同步的。

第四个单独说一下。stackalloc提供的是在线程的堆栈上分配内存。如果Span可以使用异步,会导致一个线程可以访问另一个线程的堆栈。显然这是不安全和不合理的。所以,保持Span同步是必须的。

所以,Span就是一个性能非常好的,针对连续内存的同步访问器。

2. Memory

Memory,就是一个实际的内存块。

与Span不同,Memory可以在异步流中使用,同时,它还提供了获取同步访问器的方法 Memory<T>.Span()

Memory可以有多种来源,例如:

  • 数组切片

  • MemoryMarshal 的各种 Create 方法,例如 MemoryMarshal.CreateFromPinnedArray() 这样的。

第一个是最基本的用法,从数组T[]中取一个切片成为Memory。

第二个方法会复杂一些,用了一个特殊的方法来创建Memory。像上边的例子,CreateFromPinnedArray用了一个已经固定的数组。在Dotnet中,可以通过固定一个对象,来禁止GC移动对象。这在将Memory传递给非托管对象时非常有用。

总之,Memory就是一个实际的内存块。这个内存块可以被用到任何地方,并可以使用它的同步访问器Span进行访问。

3. ReadOnlyX

印象中有三种:ReadOnlySpan、ReadOnlyMemory、ReadOnlySequence。

没什么特别的,就是ReadOnly,只读啦。

前两个,ReadOnlySpan、ReadOnlyMemory,就是Span和Memory对应的只读对象。

4. ReadOnlySequence

ReadOnlySequence也不算复杂,就是一个ReadOnlyMemory元素的序列。

基于操作系统的内存管理,有时候Memory不是连续的,可能会分片段,所以就需要有个结构来表示一个Memory链/Memory列表类似的序列。这是ReadOnlySequence的由来,而它本身也是一个ReadOnlyMemory的列表。

同时,它也提供了一些属性来优化序列中包含一个元素的情况:

  • IsSingleSegment,用来快速检查是否只包含一个内存项

  • FirstSpan,该速访问ReadOnlySpan访问器的第一个内存项

因此虽然被定义为序列,但处理单个元素,例如单个Span或Memory也容易很多。

这就是今天的全部内容了。

有没有跟你用的不一样?

文章最后,再次祝大家牛年大吉,万事胜意~

喜欢就来个三连,让更多人因你而受益


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK