Repository navigation
Precompute serialization flags; leave @LoadOnly out of the encode order (plan item 3.6) - #4408
Open
evanchooly wants to merge 1 commit into
Open
evanchooly wants to merge 1 commit into
evanchooly wants to merge 1 commit into
Conversation
…er (plan item 3.6) MorphiaPropertySerialization read three config values and scanned the property's annotations for every value it checked. The config is immutable and the annotations are fixed once a property is mapped, so it now works out storeNulls, storeEmpties and whether the property is never written (@loadonly, or a final field with ignoreFinals) when it's built. The codec plan's encode order also leaves out @loadonly properties, which no encoder writes, and EntityEncoder writes the document's start and end directly instead of through a capturing lambda.
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The focused changes preserve serialization and merge semantics, with no unresolved blocking issues identified.
No open issues 🎉
What changed in this PR
This PR reduces per-property encoding work in Morphia by precomputing serialization decisions and avoiding unnecessary encoder operations, while preserving merge behavior.
Changes:
- Cache null, empty-value, and never-serialized flags when properties are mapped.
- Exclude
@LoadOnlyproperties from encode order and write document boundaries directly without a capturing lambda. - Add encode-order tests for both mappers and mark plan item 3.6 complete.
| File | Description |
|---|---|
design/mapping-game-plan.md |
Marks serialization optimization item 3.6 complete. |
core/src/test/java/dev/morphia/mapping/codec/pojo/TestCodecPlanEncodeOrder.java |
Tests property order and id/@LoadOnly exclusion under both mappers. |
core/src/main/java/dev/morphia/mapping/codec/pojo/EntityEncoder.java |
Replaces the document-wrapper lambda with direct writer calls. |
core/src/main/java/dev/morphia/mapping/codec/pojo/CodecPlan.java |
Removes @LoadOnly properties from encode order. |
core/src/main/java/dev/morphia/mapping/codec/MorphiaPropertySerialization.java |
Precomputes flags used by serialization checks. |
Review effort: Balanced
This branch has not been deployed
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.
Plan item 3.6 (review B11/A7).
The problem
For every property of every encoded entity,
MorphiaPropertySerialization.shouldSerialize:storeNulls,ignoreFinalsandstoreEmptiesfrom the config (Booleangetters with defaults);annotationType()on each, which is a JDK proxy call for reflection-mapped annotations, just to find@LoadOnly.All of that is fixed once the property is mapped. The encoder also visited
@LoadOnlyproperties that it would never write, and wrapped every document in a capturing lambda.Change
MorphiaPropertySerializationworks outstoreNulls,storeEmptiesandneverSerialized(@LoadOnly, or a final field underignoreFinals) in its constructor.MorphiaConfigis immutable and the annotations are fixed by then, so the results are identical.shouldSerializeis now a few boolean checks plus the empty-collection test.CodecPlan.encodeOrder(from 3.0) also leaves out@LoadOnlyproperties. It already used==for the id, which the plan item also asked for.EntityEncoder.encodewrites the document's start and end directly instead of passing a capturing lambda toCodecHelper.document.Tests
TestCodecPlanEncodeOrderruns under both mappers onHarnessRenames. The encode order is the model's properties minus the id and the@LoadOnlylegacyproperty, in model order.shouldSerializebehavior under everystoreNulls/storeEmptiescombination, plus@LoadOnly, and are unchanged.-Dmorphia.mapper=critterand with reflection: 1494 + 5 tests, 0 failures.JMH
Expect a small gain. The review estimated "a few ns per property". This change is encode-only, and
decodecode is untouched.Full
CodecBenchmark,master(7bcb775f4b0) vs this branchSame machine and settings as the earlier items, before and after back to back.
reflection
critter
This run was noisy: critter decode cells moved by up to ±8% even though decode code is unchanged, which sets the noise floor for this session. The encode deltas the review predicted are smaller than that, so I reran encode on its own.
encodeonly, master and this branch alternating, three rounds eachReading it:
Decisions to review
@LoadOnlyproperties leave the encode order, not every always-skipped property as the plan said.MergingEncoder, used bymerge(), relies on visiting skipped properties. A final field skipped byignoreFinalsproduces an$unsetthere. So those properties have to stay in the order.@LoadOnlyproperties are the only ones that neither encoder writes or unsets.