数据写入规则IBufferWriter<T>

2022-06-30 13:37:25

        IBufferWriter<T>从名字上看大概已经猜到作用,这个接口是在.NET Standard 2.1作为标准支持。那这个接口的实际使用场和作用是什么?在了解之前先看一下System.Text.Json的一些代码:



public sealed class Utf8JsonWriter : IAsyncDisposable, IDisposable
{
        public Utf8JsonWriter(IBufferWriter<byte> bufferWriter, JsonWriterOptions options = default);  
        public Utf8JsonWriter(Stream utf8Json, JsonWriterOptions options = default);
}

以下是.net core针对json序列化的数据写入对象,有两个造函数分别是Stream和IBufferWriter<byte>。Stream相信不用介绍了,它是基础数据流读写规范,基本它派生出来的有FileStream,MemoryStream,NetworkStream等等,通过这个读写规范的抽象可以在读写数据的时候完全不用关心实际的数据源。那为什么要现在要引入IBufferWriter<byte>,它的好处是在那里?

IBufferWriter<byte>

        在了解它之前需要知道它具体的作用是什么,以下是接口的定义

public interface IBufferWriter<T>
{
        void Advance(int count);
        Memory<T> GetMemory(int sizeHint = 0);
        Span<T> GetSpan(int sizeHint = 0);
    }

IBufferWriter的行为接口规范很简单,两个分配内存空间的方法,和一个确定写入数据数量的方法。简单来说使用不管内存分配的,需要的时候从相关方法获取内存空间,当内存空间操作完成后通过Advance方法告诉给提供。

Stream

        在对比差别之前先看一下Stream的写入方法是怎样的

public abstract void Write(byte[] buffer, int offset, int count);
public virtual void Write(ReadOnlySpan<byte> buffer);
public Task WriteAsync(byte[] buffer, int offset, int count);
public virtual ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default);
public virtual void WriteByte(byte value);

以上是Stream写入数据的规范,它提供了一系列针对Bytes的写入操作。

两者的差别

        通过两者的提供的方法,否能了解Streram和IBufferWriter的差别?其实两者的功能都是数据写入,Stream规范了数据写入方式,但无法给外部分配内存;而IBufferWriter则规范了对外的分配内存,但并没有规范数据写入方式。

        显然Stream在写入上更规范,但为什么还要定义IBufferWriter?其实一切都是为了性能!由于Stream给外部申请内存空间,就意味着所有的写入行为都是对参数buffer一个拷贝;而IBufferWriter则有所不同,它只管理空间分配和最终提交数量,在写的过程中并不管控处理,使用者在获取分配的空间后即可直接操作。

使用

        既然这个规范是为了提高性能,而dotnet core的组件又开始支持,所以Beetlex在计划的版本中也相应支持

        public void Write(PipeStream stream, HttpResponse response)
        {
            var buffer = stream.CreateBufferWriter();
            var writer = new Utf8JsonWriter(buffer, new JsonWriterOptions { SkipValidation = true });
            writer.Reset(buffer);
            JsonSerializer.Serialize(writer, Data);
        }

以上是System.Text.Json使用BeetleX PipeStream基于IBufferWrite的扩展,其实原理是JsonSerializer从IBufferWriter中获取一小块内存,写满后提交然后再次申请写入,直到整个对象的序列化完成。

  • 作者:dotNET跨平台
  • 原文链接:https://blog.csdn.net/sD7O95O/article/details/113487950
    更新时间:2022-06-30 13:37:25