Uploaded image for project: 'yangtools'
  1. yangtools
  2. YANGTOOLS-1020

Add runtime-generated Immutable maps

    XMLWordPrintable

Details

    • New Feature
    • Status: Confirmed
    • Medium
    • Resolution: Unresolved
    • None
    • 14.0.0
    • data-impl
    • None

    Description

      Heap dump analysis of an OFP-related use case is showing that even though we are using ImmutableOffsetMaps to hold children, those maps still account for 2.4M (10%) objects holding 55MiB (9%) shallow memory, with additional 55MiB (9%) retained by their Object[]s.

      The Object array size ranges from 2 to 12 elements, which means they have 60% to 20% overhead.

      We should be able to bring these overheads down by application of runtime code generation, where we'd generate the equivalent of ImmutableOffsetMap.Unordered, where the values are stored directly in fields of the generated class. This would eliminate the need for Object[]s – i.e. 7% of heap occupancy.

      Code generation should be based on Byte-Buddy, i.e. generate bytecode.

      The implementation should assume NodeIdentifier addressing, i.e. the keys are strictly based on QNames. These should be destructured during internal dispatch, so that we first compare QNameModule portion (which is typically unique, but there may be others, i.e. in case of augment), then we should perform a simple switch() on localName.

      The bytecode should be roughly equivalent to:

      // Hand-coded base class
      public abstract class AbstractNodeIdentifierMap<V> extends AbstractMap<NodeIdentifier, V> implements Immutable {
        @Override
        public final V get(Object obj) {
          return obj instanceof NodeIdentifier nid ? get(nid.getType()) : null;
        }
      
        protected abstract V get(QName qname);
      }
      
      // Generated
      final class NodeIdenfierMapXXYYZZ<V> extends AbstractNodeIdentifierMap<V> {
        // ... for each child QNameModule
        private static final QNameModule MODULE0;
        // ... also we may need constants for QNames for things like entrySet(), keySet(), etc.
        
        // actually something reasonably-derived from QName?
        private final V v0_0;
        private final V v0_1;
      
        @Override
        protected V get(QName qnamej) {
          final var module = qname.getModule();
          if (MODULE0.equals(module)) {
              return get0(qname.getLocalName());
          }
          // else ... if we have more QNameModule
      
          return null;
        }
      
        // peeled for each QNameModule
        private V get0(String localName) {
          return switch (localName) {
            case "some-name" -> field0_0;
            case "other-name" -> field0_1;
            default -> null;
          }
        }
      }
      

      Attachments

        Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

              Unassigned Unassigned
              rovarga Robert Varga
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated: