From c11e67a96fa21438d6dd66b03224fad75f42d3d1 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Mon, 3 Feb 2020 04:02:11 +0100 Subject: [PATCH] Do not expand schema tree values When we are constructing a dataTree from a schemaTree, we do not want to operate on the ImmutableMap result, as that results in the values view being retained. This amounts to unnecessary overhead, as we typically do not need this view and it should be materialized only if it is needed. JIRA: YANGTOOLS-652 Change-Id: I3d1d689366a48822324c442da184496d9c6d873b Signed-off-by: Robert Varga --- .../AbstractDeclaredEffectiveStatement.java | 18 +++++--- ...AbstractSchemaEffectiveDocumentedNode.java | 45 +++++++------------ 2 files changed, 28 insertions(+), 35 deletions(-) diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/AbstractDeclaredEffectiveStatement.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/AbstractDeclaredEffectiveStatement.java index c6987477ee..4ca71b8df1 100644 --- a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/AbstractDeclaredEffectiveStatement.java +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/AbstractDeclaredEffectiveStatement.java @@ -12,6 +12,7 @@ import static java.util.Objects.requireNonNull; import com.google.common.annotations.Beta; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import java.util.Map; import java.util.Optional; import org.eclipse.jdt.annotation.NonNull; @@ -175,14 +176,14 @@ public abstract class AbstractDeclaredEffectiveStatement, E extends SchemaTreeAwareEffectiveStatement> extends WithSchemaTree { - private final @NonNull Map> schemaTree; + private final @NonNull ImmutableMap> schemaTree; private final @NonNull D declared; protected DefaultWithSchemaTree(final D declared, final StmtContext ctx, final ImmutableList> substatements) { this.declared = requireNonNull(declared); - this.schemaTree = AbstractSchemaEffectiveDocumentedNode.createSchemaTreeNamespace( - ctx.getStatementSourceReference(), substatements); + this.schemaTree = ImmutableMap.copyOf(AbstractSchemaEffectiveDocumentedNode.createSchemaTreeNamespace( + ctx.getStatementSourceReference(), substatements)); } @Override @@ -206,16 +207,19 @@ public abstract class AbstractDeclaredEffectiveStatement, E extends DataTreeAwareEffectiveStatement> extends WithDataTree { - private final @NonNull Map> schemaTree; - private final @NonNull Map> dataTree; + private final @NonNull ImmutableMap> schemaTree; + private final @NonNull ImmutableMap> dataTree; private final @NonNull D declared; protected DefaultWithDataTree(final D declared, final StmtContext ctx, final ImmutableList> substatements) { this.declared = requireNonNull(declared); final StatementSourceReference ref = ctx.getStatementSourceReference(); - this.schemaTree = AbstractSchemaEffectiveDocumentedNode.createSchemaTreeNamespace(ref, substatements); - this.dataTree = AbstractSchemaEffectiveDocumentedNode.createDataTreeNamespace(ref, schemaTree); + final Map> schema = + AbstractSchemaEffectiveDocumentedNode.createSchemaTreeNamespace(ref, substatements); + this.schemaTree = ImmutableMap.copyOf(schema); + this.dataTree = AbstractSchemaEffectiveDocumentedNode.createDataTreeNamespace(ref, schema.values(), + schemaTree); } @Override diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/AbstractSchemaEffectiveDocumentedNode.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/AbstractSchemaEffectiveDocumentedNode.java index 6b2ca676b5..11354c5128 100644 --- a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/AbstractSchemaEffectiveDocumentedNode.java +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/AbstractSchemaEffectiveDocumentedNode.java @@ -15,10 +15,8 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import java.lang.invoke.VarHandle; import java.util.Collection; -import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; -import java.util.Map.Entry; import java.util.Optional; import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.yangtools.yang.common.QName; @@ -47,8 +45,8 @@ import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReferenc @Beta public abstract class AbstractSchemaEffectiveDocumentedNode> extends AbstractEffectiveDocumentedNode { - private final Map> dataTreeNamespace; - private final Map> schemaTreeNamespace; + private final ImmutableMap> dataTreeNamespace; + private final ImmutableMap> schemaTreeNamespace; protected AbstractSchemaEffectiveDocumentedNode(final StmtContext ctx) { super(ctx); @@ -56,14 +54,18 @@ public abstract class AbstractSchemaEffectiveDocumentedNode> schemaTree; if (this instanceof SchemaTreeAwareEffectiveStatement || this instanceof DataNodeContainer) { - schemaTreeNamespace = createSchemaTreeNamespace(ctx.getStatementSourceReference(), + schemaTree = createSchemaTreeNamespace(ctx.getStatementSourceReference(), effectiveSubstatements()); } else { - schemaTreeNamespace = ImmutableMap.of(); + schemaTree = ImmutableMap.of(); } - if (this instanceof DataTreeAwareEffectiveStatement && !schemaTreeNamespace.isEmpty()) { - dataTreeNamespace = createDataTreeNamespace(ctx.getStatementSourceReference(), schemaTreeNamespace); + schemaTreeNamespace = ImmutableMap.copyOf(schemaTree); + + if (this instanceof DataTreeAwareEffectiveStatement && !schemaTree.isEmpty()) { + dataTreeNamespace = createDataTreeNamespace(ctx.getStatementSourceReference(), schemaTree.values(), + schemaTreeNamespace); } else { dataTreeNamespace = ImmutableMap.of(); } @@ -104,16 +106,18 @@ public abstract class AbstractSchemaEffectiveDocumentedNode> schemaChildren = new LinkedHashMap<>(); substatements.stream().filter(SchemaTreeEffectiveStatement.class::isInstance) .forEach(child -> putChild(schemaChildren, (SchemaTreeEffectiveStatement) child, ref, "schema")); - return toImmutable(schemaChildren); + return schemaChildren; } - static @NonNull Map> createDataTreeNamespace( + static @NonNull ImmutableMap> createDataTreeNamespace( final StatementSourceReference ref, - final Map> schemaTreeNamespace) { + final Collection> schemaTreeStatements, + // Note: this dance is needed to not retain ImmutableMap$Values + final ImmutableMap> schemaTreeNamespace) { final Map> dataChildren = new LinkedHashMap<>(); boolean sameAsSchema = true; - for (SchemaTreeEffectiveStatement child : schemaTreeNamespace.values()) { + for (SchemaTreeEffectiveStatement child : schemaTreeStatements) { if (child instanceof DataTreeEffectiveStatement) { putChild(dataChildren, (DataTreeEffectiveStatement) child, ref, "data"); } else { @@ -124,22 +128,7 @@ public abstract class AbstractSchemaEffectiveDocumentedNode Map toImmutable(final Map map) { - switch (map.size()) { - case 0: - return ImmutableMap.of(); - case 1: - // Special case: singleton ImmutableMap is actually SingletonImmutableBiMap, which allocates its inverse - // view and its keySet() when asked for values() -- which costs us 64 bytes (40+24). - // java.util.Collections can do the same job for less memory. - final Entry entry = map.entrySet().iterator().next(); - return Collections.singletonMap(entry.getKey(), entry.getValue()); - default: - return ImmutableMap.copyOf(map); - } + return sameAsSchema ? (ImmutableMap) schemaTreeNamespace : ImmutableMap.copyOf(dataChildren); } @SuppressWarnings("unchecked") -- 2.36.6