Skip to content

Avoid intermediate string allocation in Newtonsoft websocket deserialization#677

Open
maedula wants to merge 1 commit into
graphql-dotnet:masterfrom
maedula:perf/newtonsoft-websocket-deserialize-avoid-string-copy
Open

Avoid intermediate string allocation in Newtonsoft websocket deserialization#677
maedula wants to merge 1 commit into
graphql-dotnet:masterfrom
maedula:perf/newtonsoft-websocket-deserialize-avoid-string-copy

Conversation

@maedula

@maedula maedula commented Jul 16, 2026

Copy link
Copy Markdown

Summary

  • deserialize websocket response bytes directly through JsonTextReader instead of first allocating a complete UTF-8 string
  • preserve JsonConvert.DefaultSettings by using JsonSerializer.CreateDefault
  • preserve rejection of trailing JSON content and keep websocket input UTF-8-only
  • add regression coverage for trailing content and global Newtonsoft settings

Validation

  • dotnet test tests/GraphQL.Client.Serializer.Tests/GraphQL.Client.Serializer.Tests.csproj -c Release
  • 68 tests passed

…r.DeserializeToWebsocketResponse

DeserializeToWebsocketResponse<TResponse>(byte[]) called Encoding.UTF8.GetString(bytes)
to materialize the whole websocket payload as a UTF-16 string before handing it to
JsonConvert.DeserializeObject. This doubles the memory footprint of every incoming
websocket message and is unnecessary: Newtonsoft.Json can read directly from a stream
via JsonTextReader, exactly like the sibling DeserializeFromUtf8Stream helper in the
same class already does, and like SystemTextJsonSerializer.DeserializeToWebsocketResponse
already does by parsing the ReadOnlySpan<byte> directly.

This showed up as a measurable allocation hotspot in a production application that
processes a high-volume GraphQL subscription over websockets (many messages/sec).

Also adds a DeserializeToWebsocketResponseTest to BaseSerializerTest, since
DeserializeToWebsocketResponse previously had no direct test coverage (only the
Utf8Stream path was tested).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant