dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.03k stars 4.67k forks source link

JsonElement vs JsonDocument Parse: why no UseArrayPools #108157

Open frivard-coveo opened 3 days ago

frivard-coveo commented 3 days ago

Description

My program is looping over a lot of json, and we are encountering a lot of GC pressure. I was digging into the code trying to understand what we are doing wrong. My findings led me to

but.. if instead my custom converter returns a 'JsonDocument' (and later on I take its RootElement), the built-in JsonDocumentConverted ends up calling https://source.dot.net/#System.Text.Json/System/Text/Json/Document/JsonDocument.Parse.cs,420

Notice the difference? The main difference here is that JsonDocumentConverter path is UseArrayPools=true, while JsonElementConverter path is UseArrayPools=false, although both of them ask to build a JsonDocument out of the stream.

I know a lot of care, lots of reviews, from very clever individuals go into such libraries. I'd just like to know : why ? Why not use array pools for JsonElements? Put it another way: if instead of deserializing to a JsonElement I deserialize to a JsonDocument and take its RootElement, am I exposing myself to memory corruption issues (because of the ArrayPool underneath) ?

Configuration

.NET 8 on both Windows and Linux.

Regression?

No, was like that before.

Analysis

My colleague pointed out that JsonElement is a struct, and JsonDocument a class. However I fail to see the impact on using array pools or not to back the JsonDocument.

dotnet-policy-service[bot] commented 3 days ago

Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis See info in area-owners.md if you want to be subscribed.

stephentoub commented 3 days ago

Why not use array pools for JsonElements?

Where/when would the array be released back to the pool?

eiriktsarpalis commented 3 days ago

It's what Stephen said. There's no point in using array pools unless there is a mechanism for returning used buffers to the pool. JsonDocument achieves this by implementing IDisposable but JsonElement is different and cannot do the same.