BENCHMARKS · SERIALIZATION
System.Text.Json (reflection and source-gen) vs Newtonsoft, both directions. Suite and raw reports: github.com/gdhami-net/dotnet-benchmarks.
SerializeOrders
Serialize the same order list three ways: reflection-based System.Text.Json, its source-generated twin, and Newtonsoft.Json.
TAKEAWAY Turn on the source generator: same API, same output, roughly a quarter faster and AOT-safe. Keep Newtonsoft only where its features (converters, LINQ-to-JSON) are actually used.
In this run: Stj_sourcegen is fastest — 1.5× faster than the baseline.
In this run: Stj_sourcegen is fastest — 1.5× faster than the baseline.
RESULTS — 100
| method | net9.0 | net10.0 | ratio | allocated | Δ net10.0 |
|---|---|---|---|---|---|
| Stj_reflection baseline | 16.1 µs ±156 ns | 15.2 µs ±857 ns | 1.00× | 21.7 KB | -6% |
| Stj_sourcegen | 12.7 µs ±1.0 µs | 10.1 µs ±752 ns | 0.67× | 21.4 KB | -20% |
| Newtonsoft_json | 33.2 µs ±269 ns | 30.6 µs ±382 ns | 2.02× | 70.0 KB | -8% |
RATIO VS BASELINE — 100 · net10.0
RESULTS — 10000
| method | net9.0 | net10.0 | ratio | allocated | Δ net10.0 |
|---|---|---|---|---|---|
| Stj_reflection baseline | 2.18 ms ±26.0 µs | 1.95 ms ±41.0 µs | 1.00× | 2.18 MB | -11% |
| Stj_sourcegen | 1.77 ms ±36.1 µs | 1.50 ms ±33.5 µs | 0.77× | 2.17 MB | -15% |
| Newtonsoft_json | 4.30 ms ±114.6 µs | 3.88 ms ±52.2 µs | 1.99× | 5.80 MB | -10% |
RATIO VS BASELINE — 10000 · net10.0
SCALING · net10.0 · MEAN TIME BY INPUT SIZE (LOG)
Stj_reflectionStj_sourcegenNewtonsoft_json
THE LEDGER · SAME WORKLOAD ACROSS RELEASES (LOG)
Stj_reflectionStj_sourcegenNewtonsoft_json
THE CODE BEING MEASURED
Stj_reflection — what this measures
System.Text.Json with reflection-driven metadata — the default most codebases run.
[Benchmark (Baseline)]
public string Stj_reflection()
=> JsonSerializer.Serialize(_orders);Stj_sourcegen — what this measures
System.Text.Json with compile-time source-generated metadata — no runtime reflection.
[Benchmark]
public string Stj_sourcegen()
=> JsonSerializer.Serialize(_orders, OrderJsonContext.Default.ListOrder);Newtonsoft_json — what this measures
Newtonsoft.Json — the library much of .NET migrated from.
[Benchmark]
public string Newtonsoft_json()
=> Newtonsoft.Json.JsonConvert.SerializeObject(_orders);DeserializeOrders
Read the same JSON back: reflection vs source-generated System.Text.Json vs Newtonsoft.
TAKEAWAY Deserialization is where serializer choice hurts most - it runs on every request you receive. Source-gen System.Text.Json is the default to standardize on.
In this run: Stj_sourcegen is fastest — 1.0× faster than the baseline.
In this run: Stj_sourcegen is fastest — 1.0× faster than the baseline.
RESULTS — 100
| method | net9.0 | net10.0 | ratio | allocated | Δ net10.0 |
|---|---|---|---|---|---|
| Stj_reflection baseline | 35.8 µs ±144 ns | 34.9 µs ±1.4 µs | 1.00× | 42.5 KB | -2% |
| Stj_sourcegen | 37.4 µs ±1.5 µs | 34.0 µs ±1.9 µs | 0.97× | 42.5 KB | -9% |
| Newtonsoft_json | 59.1 µs ±3.0 µs | 52.0 µs ±2.8 µs | 1.49× | 96.1 KB | -12% |
RATIO VS BASELINE — 100 · net10.0
RESULTS — 10000
| method | net9.0 | net10.0 | ratio | allocated | Δ net10.0 |
|---|---|---|---|---|---|
| Stj_reflection baseline | 4.89 ms ±406.0 µs | 4.31 ms ±262.0 µs | 1.00× | 4.16 MB | -12% |
| Stj_sourcegen | 4.52 ms ±112.7 µs | 4.45 ms ±324.2 µs | 1.03× | 4.19 MB | -2% |
| Newtonsoft_json | 7.47 ms ±412.7 µs | 6.57 ms ±244.1 µs | 1.52× | 9.19 MB | -12% |
RATIO VS BASELINE — 10000 · net10.0
SCALING · net10.0 · MEAN TIME BY INPUT SIZE (LOG)
Stj_reflectionStj_sourcegenNewtonsoft_json
THE LEDGER · SAME WORKLOAD ACROSS RELEASES (LOG)
Stj_reflectionStj_sourcegenNewtonsoft_json
THE CODE BEING MEASURED
Stj_reflection — what this measures
System.Text.Json, reflection-driven metadata.
[Benchmark (Baseline)]
public List<Order>? Stj_reflection()
=> JsonSerializer.Deserialize<List<Order>>(_json);Stj_sourcegen — what this measures
System.Text.Json, source-generated metadata.
[Benchmark]
public List<Order>? Stj_sourcegen()
=> JsonSerializer.Deserialize(_json, OrderJsonContext.Default.ListOrder);Newtonsoft_json — what this measures
Newtonsoft.Json.
[Benchmark]
public List<Order>? Newtonsoft_json()
=> Newtonsoft.Json.JsonConvert.DeserializeObject<List<Order>>(_json);speed vs allocation
Fast is one axis. What it costs the GC is the other.
Stj_reflectionStj_sourcegenNewtonsoft_jsonStj_reflectionStj_sourcegenNewtonsoft_json