From 5f540931c1f8972b59e51556b6cba14b2c8f3f40 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Wed, 29 May 2019 12:10:52 +0200 Subject: [PATCH] Optimize NodeIdentifier reading NodeIdentifiers are just an alias for QName, which is heavily reused. This patch adds a secondary cache for interpreting QNames as NodeIdentifiers, with instance reuse. This allows us to reduce the number of NodeIdentifier instances, while not relying on NodeIdentifier.create() for the common lookup case. JIRA: CONTROLLER-1898 Change-Id: Ifa0c5d572f7d39da49707529c7ddd9c9f36f2dab Signed-off-by: Robert Varga --- ...ithiumNormalizedNodeInputStreamReader.java | 3 +- ...SodiumNormalizedNodeInputStreamReader.java | 50 +++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/LithiumNormalizedNodeInputStreamReader.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/LithiumNormalizedNodeInputStreamReader.java index 9f523555bb..3b4f2dad05 100755 --- a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/LithiumNormalizedNodeInputStreamReader.java +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/LithiumNormalizedNodeInputStreamReader.java @@ -252,8 +252,7 @@ class LithiumNormalizedNodeInputStreamReader extends ForwardingDataInput impleme return new AugmentationIdentifier(readQNameSet()); } - private NodeIdentifier readNodeIdentifier() throws IOException { - // FIXME: we should have a cache for these, too + NodeIdentifier readNodeIdentifier() throws IOException { return new NodeIdentifier(readQName()); } diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/SodiumNormalizedNodeInputStreamReader.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/SodiumNormalizedNodeInputStreamReader.java index eb7e9f1b8a..4890180115 100644 --- a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/SodiumNormalizedNodeInputStreamReader.java +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/SodiumNormalizedNodeInputStreamReader.java @@ -7,14 +7,18 @@ */ package org.opendaylight.controller.cluster.datastore.node.utils.stream; +import static com.google.common.base.Verify.verify; + import java.io.DataInput; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; final class SodiumNormalizedNodeInputStreamReader extends LithiumNormalizedNodeInputStreamReader { + private final ArrayList codedNodeIdentifiers = new ArrayList<>(); private final List codedAugments = new ArrayList<>(); private final List codedQNames = new ArrayList<>(); @@ -53,6 +57,52 @@ final class SodiumNormalizedNodeInputStreamReader extends LithiumNormalizedNodeI } } + @Override + NodeIdentifier readNodeIdentifier() throws IOException { + // NodeIdentifier rides on top of QName, with this method really saying 'interpret next QName as NodeIdentifier' + // to do that we inter-mingle with readQName() + final byte valueType = readByte(); + switch (valueType) { + case TokenTypes.IS_QNAME_CODE: + return codedNodeIdentifier(readInt()); + case TokenTypes.IS_QNAME_VALUE: + return rawNodeIdentifier(); + default: + throw new IOException("Unhandled QName value type " + valueType); + } + } + + private NodeIdentifier codedNodeIdentifier(final int code) throws IOException { + final NodeIdentifier existing = codedNodeIdentifiers.size() > code ? codedNodeIdentifiers.get(code) : null; + return existing != null ? existing : storeNodeIdentifier(code, codedQName(code)); + } + + private NodeIdentifier rawNodeIdentifier() throws IOException { + // Capture size before it incremented + final int code = codedQNames.size(); + return storeNodeIdentifier(code, rawQName()); + } + + private NodeIdentifier storeNodeIdentifier(final int code, final QName qname) { + final NodeIdentifier ret = NodeIdentifier.create(qname); + final int size = codedNodeIdentifiers.size(); + + if (code >= size) { + // Null-fill others + codedNodeIdentifiers.ensureCapacity(code + 1); + for (int i = size; i < code; ++i) { + codedNodeIdentifiers.add(null); + } + + codedNodeIdentifiers.add(ret); + } else { + final NodeIdentifier check = codedNodeIdentifiers.set(code, ret); + verify(check == null); + } + + return ret; + } + private QName codedQName(final int code) throws IOException { try { return codedQNames.get(code); -- 2.36.6