Skip to content

Commit eb01d94

Browse files
committed
Optimize JSON runtime and expand benchmarks
1 parent 09a6ed1 commit eb01d94

14 files changed

Lines changed: 1588 additions & 304 deletions

README.md

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,10 @@ Compared with DTO-heavy designs, the difference is:
218218
- Shared compatibility coverage lives in [tests/CodecMapper.CompatibilitySentinel](/home/adam/projects/CodecMapper/tests/CodecMapper.CompatibilitySentinel), with thin Native AOT and Fable shell apps under [tests/CodecMapper.AotTests](/home/adam/projects/CodecMapper/tests/CodecMapper.AotTests) and [tests/CodecMapper.FableTests](/home/adam/projects/CodecMapper/tests/CodecMapper.FableTests).
219219
- CI runs both the .NET sentinel app and a real Fable transpilation check of the Fable sentinel project.
220220
- The shared sentinel now includes selected invalid and out-of-range numeric cases, so the portability story covers failure behavior as well as happy-path round-trips.
221+
222+
## Performance Work
223+
224+
When benchmark numbers move, profile before changing the runtime. The repo now includes a repeatable `perf` workflow for the manual benchmark runner in [docs/HOW_TO_PROFILE_BENCHMARK_HOT_PATHS.md](docs/HOW_TO_PROFILE_BENCHMARK_HOT_PATHS.md).
221225
- The contract bridge in [src/CodecMapper.Bridge](/home/adam/projects/CodecMapper/src/CodecMapper.Bridge) is `.NET`-only by design; the portable surface is the core schema/JSON/XML library in [src/CodecMapper](/home/adam/projects/CodecMapper/src/CodecMapper).
222226

223227
## Docs
@@ -245,26 +249,28 @@ For BenchmarkDotNet output, use:
245249
dotnet run -c Release --project benchmarks/CodecMapper.Benchmarks/CodecMapper.Benchmarks.fsproj
246250
```
247251

248-
The benchmark suite compares `CodecMapper` JSON encode/decode against `System.Text.Json` and `Newtonsoft.Json` on the same deterministic batch of `100` nested records.
252+
The benchmark suite compares `CodecMapper` JSON encode/decode against `System.Text.Json` and `Newtonsoft.Json` across a deterministic scenario matrix that covers small messages, nested-record batches, string-heavy payloads, numeric-heavy telemetry, and decode paths with ignored unknown fields.
249253

250254
<!-- benchmark-snapshot:start -->
251-
Latest local manual snapshot, measured on March 10, 2026.
255+
Latest local manual scenario-matrix snapshot, measured on March 11, 2026.
252256

253-
Encode, fastest to slowest:
257+
The manual runner now covers six deterministic workloads:
254258

255-
| Library | Mean ns/op | Mean B/op |
256-
| --- | ---: | ---: |
257-
| System.Text.Json | 28158.3 | 17528.0 |
258-
| CodecMapper | 32989.8 | 63680.0 |
259-
| Newtonsoft.Json | 47202.1 | 53368.9 |
259+
- `small-message`: one shallow command-sized object
260+
- `person-batch-25`: medium nested-record API-style batch
261+
- `person-batch-250`: larger nested-record throughput batch
262+
- `escaped-articles-20`: string-heavy records with escapes and nested authors
263+
- `telemetry-500`: numeric-heavy objects with float, decimal, and wider integers
264+
- `person-batch-25-unknown-fields`: receive-side decode with ignored extra fields
260265

261-
Decode, fastest to slowest:
266+
Headline observations from the latest local run:
262267

263-
| Library | Mean ns/op | Mean B/op |
264-
| --- | ---: | ---: |
265-
| System.Text.Json | 77985.5 | 47920.3 |
266-
| CodecMapper deserialize bytes | 108412.4 | 148472.0 |
267-
| Newtonsoft.Json | 112767.2 | 90024.1 |
268+
- The latest optimization pass moved `CodecMapper` ahead on `small-message` serialize (`1.87 us` vs `2.25 us`) while keeping tiny-message decode in the same general range.
269+
- `CodecMapper` stayed effectively even with `System.Text.Json` on `person-batch-25` deserialize (`94.6 us` vs `94.7 us`) and remained competitive on `person-batch-250` serialize (`390.8 us` vs `370.8 us`).
270+
- `System.Text.Json` still leads on the string-heavy `escaped-articles-20` workload, especially on deserialize.
271+
- `System.Text.Json` also still leads the largest numeric-heavy `telemetry-500` case, which means the JSON runtime still has meaningful throughput and allocation work left on wide numeric batches.
272+
- The unknown-field decode path improved, but `System.Text.Json` still holds a modest lead on `person-batch-25-unknown-fields` deserialize (`125.8 us` vs `132.5 us`).
273+
- Both `CodecMapper` and `System.Text.Json` stayed well ahead of `Newtonsoft.Json` across every workload in this local matrix.
268274

269275
These numbers came from:
270276

0 commit comments

Comments
 (0)