Optimize JsonReaderData for MemoryStream and make buffer publicly visible for StructuralJsonTypeMappings#38051
Optimize JsonReaderData for MemoryStream and make buffer publicly visible for StructuralJsonTypeMappings#38051JoasE wants to merge 4 commits intodotnet:mainfrom
Conversation
…ible for StructuralJsonTypeMappings
|
I don’t do these types of optimizations often, but I ran into this when working on json serialization for cosmos. |
There was a problem hiding this comment.
Pull request overview
This PR optimizes JSON reading for provider-produced MemoryStream instances by allowing JsonReaderData to directly use a MemoryStream’s internal buffer (when available), avoiding duplicate buffering and reducing allocations during structural JSON materialization.
Changes:
- Updated
JsonReaderDatato store its input asReadOnlyMemory<byte>and added aMemoryStreamfast-path usingTryGetBuffer(). - Updated SQL Server structural JSON mapping to create
MemoryStreaminstances with a publicly visible buffer (soTryGetBuffer()succeeds). - Updated SQLite structural JSON mapping to use a shared
CreateUtf8Streamhelper (also creatingMemoryStreamwith a publicly visible buffer) and simplified the expression tree.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/EFCore/Storage/Json/JsonReaderData.cs | Adds MemoryStream buffer fast-path and shifts internal buffering to ReadOnlyMemory<byte> + optional mutable buffer. |
| src/EFCore.SqlServer/Storage/Internal/SqlServerStructuralJsonTypeMapping.cs | Creates UTF-8 MemoryStream with publiclyVisible: true to enable buffer reuse in JsonReaderData. |
| src/EFCore.Sqlite.Core/Storage/Internal/SqliteJsonTypeMapping.cs | Introduces CreateUtf8Stream helper and uses it from CustomizeDataReaderExpression, enabling buffer reuse. |
src/EFCore.Sqlite.Core/Storage/Internal/SqliteJsonTypeMapping.cs
Outdated
Show resolved
Hide resolved
|
BTW @JoasE our whole JSON reading architecture here is quite inefficient: we read the JSON string, and then expose that as UTF8 data as bytes to be decoded (again!) by Utf8JsonReader etc. The real perf win here would be to have have Utf8JsonReader read directly from the network with any additional buffering/decoding, see #31216. |
|
@roji Thanks for the quick review!
Good point, I guess my current changes tackle some low-hanging fruit in the meantime, which should also benefit the new Cosmos deserialization work. |
Internally managed providers pass MemoryStream to JsonReaderData. This PR makes their internal buffer accessible and optimizes JsonReaderData to leverage the internal buffer if possible. This prevents duplicate buffering for json MemoryStreams