System.IO.Pipelines: .NET上高性能IO (4)

在一个完美的世界中,读取和解析工作是一个团队:读取线程消耗来自网络的数据并将其放入缓冲区,而解析线程负责构建适当的数据结构。通常,解析将比仅从网络复制数据块花费更多时间。结果,读取线程可以轻易地压倒解析线程。结果是读取线程必须减慢或分配更多内存来存储解析线程的数据。为获得最佳性能,在频繁暂停和分配更多内存之间存在平衡。

为了解决这个问题,管道有两个设置来控制数据的流量,PauseWriterThreshold和ResumeWriterThreshold。PauseWriterThreshold决定有多少数据应该在调用PipeWriter.FlushAsync之前进行缓冲停顿。ResumeWriterThreshold控制reader消耗多少后写入可以恢复。

此处输入图片的描述

当Pipe的数据量超过PauseWriterThreshold,PipeWriter.FlushAsync会异步阻塞。数据量变得低于ResumeWriterThreshold,它会解锁时。两个值用于防止在极限附近发生反复阻塞和解锁。

IO调度

通常在使用async / await时,会在线程池线程或当前线程上调用continuation SynchronizationContext。

在执行IO时,对执行IO的位置进行细粒度控制非常重要,这样可以更有效地利用CPU缓存,这对于Web服务器等高性能应用程序至关重要。Pipelines公开了一个PipeScheduler确定异步回调运行位置的方法。这使得调用者可以精确控制用于IO的线程。

实践中的一个示例是在Kestrel Libuv传输中,其中IO回调在专用事件循环线程上运行。

PipeReader模式的其他好处:

一些底层系统支持“无缓冲等待”,即,在底层系统中实际可用数据之前,永远不需要分配缓冲区。例如,在带有epoll的Linux上,可以等到数据准备好之后再实际提供缓冲区来进行读取。这避免了具有大量线程等待数据的问题不会立即需要保留大量内存。

默认情况下Pipe,可以轻松地针对网络代码编写单元测试,因为解析逻辑与网络代码分离,因此单元测试仅针对内存缓冲区运行解析逻辑,而不是直接从网络中消耗。它还可以轻松测试那些难以测试发送部分数据的模式。ASP.NET Core使用它来测试Kestrel的http解析器的各个方面。

允许将底层OS缓冲区(如Windows上的Registered IO API)暴露给用户代码的系统非常适合管道,因为缓冲区始终由PipeReader实现提供。

其他相关类型

作为制作System.IO.Pipelines的一部分,我们还添加了许多新的原始BCL类型:

MemoryPool<T>,IMemoryOwner<T>,MemoryManager<T> - .NET Core 1.0添加了ArrayPool<T>,在.NET Core 2.1中,我们现在有一个更通用的抽象,适用于任何工作的池Memory<T>。这提供了一个可扩展点,允许您插入更高级的分配策略以及控制缓冲区的管理方式(例如,提供预先固定的缓冲区而不是纯托管的阵列)。

IBufferWriter<T> - 表示用于写入同步缓冲数据的接收器。(PipeWriter实现这个)

IValueTaskSource - ValueTask<T>自.NET Core 1.1以来就已存在,但在.NET Core 2.1中获得了一些超级权限,允许无分配的等待异步操作。有关详细信息,请参阅https://github.com/dotnet/corefx/issues/27445。

我如何使用管道?

API存在于System.IO.Pipelines nuget包中。

以下是使用管道处理基于行的消息的.NET Core 2.1服务器应用程序的示例(上面的示例)https://github.com/davidfowl/TcpEcho。它应该运行`dotnet run`(或通过在Visual Studio中运行)。它侦听端口8087上的套接字并将收到的消息写入控制台。您可以使用netcat或putty等客户端建立与8087的连接,并发送基于行的消息以使其正常工作。

今天Pipelines为Kestrel和SignalR提供支持,我们希望看见它作为.NET社区中许多网络库和组件的核心。

资料:

转载自System.IO.Pipelines: High performance IO in .NET

Pipelines - a guided tour of the new IO API in .NET, part 1

Pipelines - a guided tour of the new IO API in .NET, part 2

2号资料的中文翻译 Pipelines - .NET中的新IO API指引(一)

System.IO.Pipelines-Nuget包

PS: 首次翻译英文文章,不足错漏请指出,多谢支持

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjgss.html