Materialize Any and dict targets like the untyped parse; write Any containers statically - #486
Merged
Merged
Conversation
…ntainers statically
Reading:
- `StructUtils.make(style, Any, x)` and the `Vector{Any}`, `Object{String,Any}` and
`AbstractDict{String,Any}` targets now go through a styled `applyvalue(f, x, style)`,
the typed counterpart of the untyped materializer: each value reaches its sink with a
concrete type instead of a boxed `(value::Any, pos)` pair. A 137-key object into
`Object{String,Any}` drops from 105us/1433 allocations to 9us/428 (untyped: 425), and a
3000-key nested object from 17ms to 0.17ms (the generic dict path filled `Object`
through `setindex!`, a linear scan per key).
Writing:
- `Any`-valued dicts, vectors and pair vectors hand each of the types the untyped parse
produces to the writer statically; anything else goes through the new
`JSON.applyany(style, f, key, value)` hook, whose default lowers dynamically. A style
that overrides it to throw has no dynamic call on its write path under
`juliac --trim=safe`.
- The output buffer grows by at least doubling, so a large output no longer needs a
`sizeguess` method to avoid repeated copies.
- Nested writes under `jsonlines=true` keep the caller's `style` and `bufsize`; a custom
style was silently replaced by the default for every nested value.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #486 +/- ##
==========================================
+ Coverage 91.30% 91.75% +0.44%
==========================================
Files 7 7
Lines 1680 1794 +114
==========================================
+ Hits 1534 1646 +112
- Misses 146 148 +2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…-bit Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-ups from JuliaGeo/GeoJSON.jl#128. Typed
Anyslots and common dictionary/array targets reuse concrete callback materialization; largeObject{String,Any}targets append in linear time for distinct keys.Any-container writing uses concrete branches plus theJSON.applyanyextension point. This pairs with JuliaServices/StructUtils.jl#73 and also passes CI with released StructUtils 2.9.1.Customization contracts are preserved:
lowerkey, includingVector{Any}and undefined slots. JSON accepts a string or real number from this hook. Its default numeric method returns the number unchanged; only object writing and sorting convert it to a string. Numeric object keys remain quoted and sort lexicographically. ExistingAbstractStringkeys are not copied.lower, including nested containers and missing/null values. Concrete sorted dictionaries retain specialized writes instead of boxing each value.make,lift,liftkey, and initialization; mismatched shapes retain the generic fallback.Validation at
fc4a655eab9e8c95a27a074d3d052cb108f854ff, paired locally with StructUtils4f4e220e91b474bcd3d2cdc6bb74f9cd13aa40c1:benchmarks/geojson_regressions.jlprovides 111 runtime workloads plus cold, load, and precompile modes. The numeric-key follow-up adds no allocations across the 333 runtime comparisons on Julia 1.10/1.12/1.13 after matching cache state.The numeric-key fix retains the large-array gain while restoring all index hooks. On local macOS ARM64 / Julia 1.12, writing one million Float64 values takes 36.9 ms and 31 allocations, versus 36.8 ms and 31 allocations before this follow-up; the package base took about 102 ms and 2,000,031 allocations. Three alternating before/after samples give about 51.7 / 51.3 ms for combined cached loading and 5.84 / 5.84 s for forced package rebuilds with dependencies cached.
Tradeoffs remain explicit:
Timings are local measurements, not guarantees across machines. Safe trimming requires a closed fallback and statically resolvable custom lowering.
Co-authored by Codex