System.Text.Json: десериализация из System.IO.Pipeslines - PullRequest
2 голосов
/ 24 октября 2019

Я потребляю Json из TcpClient, и чтобы получить решение с низким распределением ресурсов и хорошей производительностью, я решил использовать новый System.IO.Pipelines для обработки ввода-вывода и System.Text.Json для десериализации. Выход из трубы составляет ReadOnlySequence<byte>. Я в порядке, когда в ReadOnlySequence есть только один сегмент, так что я могу передать этот сегмент (то есть ReadOnlySpan<byte>) десериализатору. Но что мне делать с несколькими сегментами?

То, что у меня есть, это код ниже. Но в некоторых случаях длина последовательности слишком велика, поэтому я получаю переполнение стека в stackalloc. Кроме того, создание копии данных кажется мне нарушением намерений System.IO.Pipeslines. Разве 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);
    }
}

1 Ответ

1 голос
/ 24 октября 2019

Используйте тип Utf8JsonReader, который переносит последовательность (примечание: он также может переносить диапазон и т. Д.), И позволяет ему решать проблемы с одним / несколькими / и т.д. сегментом:

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