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.9 µs ±142 ns | 15.1 µs ±129 ns | 1.00× | 21.7 KB | -11% |
| Stj_sourcegen | 12.3 µs ±100 ns | 10.0 µs ±79 ns | 0.66× | 21.4 KB | -19% |
| Newtonsoft_json | 34.3 µs ±193 ns | 31.1 µs ±319 ns | 2.06× | 70.0 KB | -10% |
RATIO VS BASELINE — 100 · net10.0
RESULTS — 10000
| method | net9.0 | net10.0 | ratio | allocated | Δ net10.0 |
|---|---|---|---|---|---|
| Stj_reflection baseline | 2.11 ms ±17.3 µs | 1.90 ms ±14.0 µs | 1.00× | 2.13 MB | -10% |
| Stj_sourcegen | 1.76 ms ±9.0 µs | 1.48 ms ±21.2 µs | 0.78× | 2.13 MB | -16% |
| Newtonsoft_json | 4.28 ms ±66.1 µs | 3.94 ms ±61.9 µs | 2.07× | 5.80 MB | -8% |
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 | 36.8 µs ±223 ns | 34.1 µs ±264 ns | 1.00× | 42.5 KB | -7% |
| Stj_sourcegen | 37.2 µs ±239 ns | 33.5 µs ±285 ns | 0.98× | 42.5 KB | -10% |
| Newtonsoft_json | 58.3 µs ±291 ns | 51.8 µs ±418 ns | 1.52× | 96.1 KB | -11% |
RATIO VS BASELINE — 100 · net10.0
RESULTS — 10000
| method | net9.0 | net10.0 | ratio | allocated | Δ net10.0 |
|---|---|---|---|---|---|
| Stj_reflection baseline | 4.63 ms ±86.2 µs | 4.43 ms ±141.9 µs | 1.00× | 4.16 MB | -4% |
| Stj_sourcegen | 4.60 ms ±119.2 µs | 4.39 ms ±134.4 µs | 0.99× | 4.16 MB | -5% |
| Newtonsoft_json | 7.44 ms ±164.0 µs | 6.77 ms ±110.7 µs | 1.53× | 9.19 MB | -9% |
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