[YANGTOOLS-490] Create SchemaContext-aware NormalizedNodes Created: 19/Aug/15  Updated: 10/Apr/22

Status: Confirmed
Project: yangtools
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Improvement
Reporter: Robert Varga Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Operating System: All
Platform: All


Issue Links:
Relates
relates to YANGTOOLS-1019 Lazily-instantiated LeafNodes Resolved
relates to YANGTOOLS-1020 Add runtime-generated Immutable maps Confirmed

 Description   

Our current implementation of NormalizedNode interface is completely generic, without being tied to the SchemaContext in which those nodes are being used.

The implementation uses QName->child maps to hold child entities, which is quite wasteful, as those maps typically have the same key set or differ by non-presence of some children.

If a builder for a particular NormalizedNode were to know the SchemaNode of the entity being built, it could use that information to:

A) Validate the NormalizedNode as it is being built, which should be an optional feature, consisting of the following functionality:

A1) Checking for valid child QName
A2) Checking value type conformance (no Strings where Integer is expected)
A3) Checking value well-formedness (according to 'pattern' and 'range' statements)
A4) Checking/converting value to the canonical representation
A5) Checking NormalizedNode consistency (according to 'when' and similar statements) when .build() is called

B) Shared child keying

Given the finite-set of possible children, which we know from the SchemaNode, we can share the the information about which nodes are present across NormalizedNode instances in the global scope. This would lower the cost of keeping track of child values to:

  • a Map<QName, Integer> shared across instances with the same keyset
  • a per-instance Object[] containing child references

The Map can be implemented as an ImmutableMap, as the Integers involved will probably be coming from JVM's boxing cache.

C) (Optional) Lazy leaf children

When a child leaf is being looked up, we get provided with its identifier (and by extension, its node type). This means that structurally we need to only retain the fact that the child exists and its value. We then can instantiate a wrapper object around the value without explicitly storing it.

While this will potentially cause more object allocations to occur, our minimum memory footprint will go down, as we would not keep that wrapper object (of ~24 bytes) around.

Note that in some access patterns the JVM can use escape analysis to eliminate the allocation completely. This obviously depends on what the access pattern is and whether the producer uses some sort of value-caching (such as reusing a single global LeafNode instance).



 Comments   
Comment by Robert Varga [ 27/Aug/19 ]

Part B) has been implemented as of Ib11b8d5adc4d5509ecbbba59348638f78fc2e62b, without relying on schema, through ImmutableOffsetMaps.

Generated at Wed Feb 07 20:53:24 UTC 2024 using Jira 8.20.10#820010-sha1:ace47f9899e9ee25d7157d59aa17ab06aee30d3d.