从ReadOnlySequence <byte>获取连续的Memory <byte>

Mat*_*art 7 c# sockets .net-core

在Marc Gravell 关于这个主题的博客文章中对管道的精彩介绍之后,我正在修补用插座实现管道.

我知道Marc已经提出了Pipelines.Sockets.Unofficial ,我使用它作为参考,但我有一个问题.

似乎该方法SocketAsyncEventArgs有一个新的重载SetBuffer():SetBuffer(Memory<byte>)

看来这里的意图是与Pipes很好地集成.

我的困惑来自于Pipe.Reader.ReadAsync()返回ReadResult包含a ReadOnlySequence<byte>(ReadResult.Buffer)的事实

在这种情况下Buffer.IsSingleSegment == true,很明显该做什么:

SocketAsyncEventArgs.SetBuffer(Buffer[0])

但在有多个细分市场的情况下,我并不完全确定最佳行动方案是什么.

我当然可以byte[]从管道中获取一个并完成它,但这会产生一个副本(可能不止一个,甚至).

ReadOnlySequence<byte>这里的用途是什么?有没有办法让"记忆"代表序列的全部内容?

也许我需要重新阅读Marc的博文......

Are*_*Bal 4

据我所知:有这个,ReadOnlySequence<>.First以防万一IsSingleSegment应该给你ReadOnlyMemory<>你正在寻找的东西。对于具有更多片段的序列,我认为您应该使用以下命令迭代它们

var iSegment = seq.Start;
ReadOnlyMemory<byte> readMemory;
while(seq.TryGet(ref iSegment, out readMemory, advance: true))
{ /* do smth */ }
Run Code Online (Sandbox Code Playgroud)

或者我认为,这做了同样的事情:

foreach(var memory in seq)
{ /* do smth */ }
Run Code Online (Sandbox Code Playgroud)

如果您关心性能并且不想复制整个缓冲区(这就是 .ToArray() 扩展方法所做的),那么迭代是有意义的。
恕我直言,其目的是有效地表示非连续缓冲区。
我不确定Sequence<>实现细节,但在大多数缓冲场景中,保存几个小缓冲区(3、2)并在它们之间切换是很常见的,这样就不会分配不必要的新内存。有时将其抽象为“循环”或“环形”缓冲区。

它导致了如图所示的“顺序”内存访问模式Sequence<>