【问题标题】:System.Text.Json: deserializing from System.IO.PipelinesSystem.Text.Json:从 System.IO.Pipelines 反序列化
【发布时间】:2020-02-20 13:48:40
【问题描述】:

我正在使用来自 TcpClient 的 Json,为了获得低分配和良好性能的解决方案,我决定使用新的 System.IO.Pipelines 处理 IO 和 System.Text.Json 进行反序列化。管道的输出是ReadOnlySequence<byte>。当ReadOnlySequence 中只有一个段时我没问题,这样我就可以将这个段(即ReadOnlySpan<byte>)传递给反序列化器。但是我应该如何处理多个细分?

到目前为止,我所拥有的是下面的代码。但是在某些情况下,序列的长度太大,所以我在stackalloc 中得到了堆栈溢出。此外,在我看来,制作数据副本违反了 System.IO.Pipelines 的意图。 System.Text.Json.JsonSerializer.Deserialize 不应该有 ReadOnlySequence 过载吗?关于如何解决这个问题的任何建议?

private void ProcessLine(ReadOnlySequence<byte> sequence)
{
    if (sequence.IsSingleSegment)
    {
        _result = JsonSerializer.Deserialize<MyType>(sequence.FirstSpan, _jsonSerializerOptions);
    }
    else
    {
        Span<byte> stackSpan = stackalloc byte[(int)sequence.Length];
        sequence.CopyTo(stackSpan);
        _result = JsonSerializer.Deserialize<MyType>(stackSpan, _jsonSerializerOptions);
    }
}

【问题讨论】:

  • 旁注:在不检查长度的情况下做某事的stackalloc,首先是小的有点危险;如果我出于某种原因需要对数据进行线性化,我只会在检查长度为&lt;= 512 之后使用stackalloc。对于较大的有效载荷如果你需要线性化(你不在这里),你应该从ArrayPool&lt;byte&gt;.Shared租一个超大的数组,在超大的数组上创建一个合适大小的跨度,复制到那个并消耗它,并将数组返回到池中

标签: c# json .net-core system.text.json system.io.pipelines


【解决方案1】:

使用Utf8JsonReader 类型,它包裹一个序列(注意:它也可以包裹一个跨度等),让它处理单/多/等段问题:

private void ProcessLine(ReadOnlySequence<byte> sequence)
{
    var reader = new Utf8JsonReader(sequence);
    _result = JsonSerializer.Deserialize<MyType>(ref reader);
}

【讨论】:

  • 不幸的是,Utf8JsonReader-taking 重载 JsonSerializer.Deserialize 也会复制数据(由文档和来源确认)。这似乎与最新的 .NET Core 版本试图实现的目标背道而驰。希望将来会有PipeReader 的重载。关于如何在不复制的情况下执行此操作的任何其他想法?
  • 关于你的回答,我想知道:我们从PipeReader 得到的序列通常只是传入字节流的一个部分,对吧? JsonSerializer 是否可以逐个序列地反序列化结果,而无需一次缓冲整个传入的字节流?
  • @Timo 目前大多数序列化程序在涉及管道时都在整个有效负载上工作,因为:完全异步序列化/反序列化真的非常很难(尤其是在处理跨度时),和 b:除非您直接引用 System.IO.Pipelines,否则异步获取(读取)和异步刷新(写入)的 API 不会暴露,这会破坏抽象的想法。对于“b”,有一个 API 提案可能会将其纳入 .NET Core 3.1
  • 谢谢马克。我会说,更有理由将其作为 .NET Core 的一部分。 :-) 你有提到的 API 提案的链接吗?
  • 这是一个值得期待的简洁 API!
猜你喜欢
  • 1970-01-01
  • 2021-07-17
  • 1970-01-01
  • 1970-01-01
  • 2021-12-08
  • 1970-01-01
  • 2021-12-30
  • 2020-06-23
  • 1970-01-01
相关资源
最近更新 更多