From 3bfe9f1d2ad0a4f7ba880eb6c97d24fbea3e10ba Mon Sep 17 00:00:00 2001 From: Tony Tkacik Date: Fri, 7 Feb 2014 22:04:16 +0100 Subject: [PATCH] Performance improvements to yang.data.api.InstanceIdentifier - Changed Collections.unmodifiableMap() to ImmutableMap, which is faster and safer, since the InstanceIdentifier contract requires immutability - Added hashCode cache, which is safe, since all state captured by instance is immutable, from the moment of the object allocation. Change-Id: I4d52af24f58c63ff5870e098b2b5fc9bbb34aec4 Signed-off-by: Tony Tkacik --- .../yang/data/api/InstanceIdentifier.java | 110 +++++++++++------- 1 file changed, 71 insertions(+), 39 deletions(-) diff --git a/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/InstanceIdentifier.java b/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/InstanceIdentifier.java index b0cce8f2be..79a7f4c317 100644 --- a/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/InstanceIdentifier.java +++ b/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/InstanceIdentifier.java @@ -7,25 +7,25 @@ */ package org.opendaylight.yangtools.yang.data.api; -import java.io.Serializable; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.opendaylight.yangtools.concepts.Builder; -import org.opendaylight.yangtools.concepts.Immutable; -import org.opendaylight.yangtools.concepts.Path; -import org.opendaylight.yangtools.yang.common.QName; - -import com.google.common.collect.ImmutableList; +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.concepts.Immutable; +import org.opendaylight.yangtools.concepts.Path; +import org.opendaylight.yangtools.yang.common.QName; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; public class InstanceIdentifier implements Path, Immutable, Serializable { private static final long serialVersionUID = 8467409862384206193L; private final List path; - private transient String to_string_cache = null; + private transient String toStringCache = null; + private transient Integer hashCodeCache = null; public List getPath() { return path; @@ -40,27 +40,48 @@ public class InstanceIdentifier implements Path, Immutable, } @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((path == null) ? 0 : path.hashCode()); - return result; + public int hashCode() { + /* + * The hashCodeCache is safe, since the object contract requires immutability + * of the object and all objects referenced from this object. + * + * Used lists, maps are immutable. Path Arguments (elements) are also immutable, + * since the PathArgument contract requires immutability. + * + * The cache is thread-safe - if multiple computations occurs at the same time, + * cache will be overwritten with same result. + */ + if(hashCodeCache == null) { + final int prime = 31; + int result = 1; + result = prime * result + ((path == null) ? 0 : path.hashCode()); + hashCodeCache = result; + } + return hashCodeCache; } @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - InstanceIdentifier other = (InstanceIdentifier) obj; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + InstanceIdentifier other = (InstanceIdentifier) obj; + if(this.hashCode() != obj.hashCode()) { + return false; + } if (path == null) { - if (other.path != null) - return false; - } else if (!path.equals(other.path)) - return false; + if (other.path != null) { + return false; + } + } else if (!path.equals(other.path)) { + return false; + } return true; } @@ -97,7 +118,7 @@ public class InstanceIdentifier implements Path, Immutable, public static final class NodeIdentifier implements PathArgument { /** - * + * */ private static final long serialVersionUID = -2255888212390871347L; @@ -107,6 +128,7 @@ public class InstanceIdentifier implements Path, Immutable, this.nodeType = node; } + @Override public QName getNodeType() { return nodeType; } @@ -145,7 +167,7 @@ public class InstanceIdentifier implements Path, Immutable, public static final class NodeIdentifierWithPredicates implements PathArgument { /** - * + * */ private static final long serialVersionUID = -4787195606494761540L; @@ -154,12 +176,12 @@ public class InstanceIdentifier implements Path, Immutable, public NodeIdentifierWithPredicates(QName node, Map keyValues) { this.nodeType = node; - this.keyValues = Collections.unmodifiableMap(new HashMap(keyValues)); + this.keyValues = ImmutableMap.copyOf(keyValues); } public NodeIdentifierWithPredicates(QName node, QName key, Object value) { this.nodeType = node; - this.keyValues = Collections.singletonMap(key, value); + this.keyValues = ImmutableMap.of(key, value); } @Override @@ -211,7 +233,7 @@ public class InstanceIdentifier implements Path, Immutable, public static final class NodeWithValue implements PathArgument { /** - * + * */ private static final long serialVersionUID = -3637456085341738431L; @@ -272,7 +294,7 @@ public class InstanceIdentifier implements Path, Immutable, private static class BuilderImpl implements InstanceIdentifierBuilder { - private final ImmutableList.Builder path; + private final ImmutableList.Builder path; public BuilderImpl() { path = ImmutableList.builder(); @@ -331,17 +353,27 @@ public class InstanceIdentifier implements Path, Immutable, } @Override - public String toString() { - if (to_string_cache != null) { - return to_string_cache; + public String toString() { + /* + * The toStringCache is safe, since the object contract requires immutability + * of the object and all objects referenced from this object. + * + * Used lists, maps are immutable. Path Arguments (elements) are also immutable, + * since the PathArgument contract requires immutability. + * + * The cache is thread-safe - if multiple computations occurs at the same time, + * cache will be overwritten with same result. + */ + if (toStringCache != null) { + return toStringCache; } StringBuilder builder = new StringBuilder(); for (PathArgument argument : path) { builder.append("/"); builder.append(argument.toString()); } - to_string_cache = builder.toString(); - return to_string_cache; + toStringCache = builder.toString(); + return toStringCache; } public static InstanceIdentifierBuilder builder(QName node) { -- 2.36.6