IGNITE-2508: Fixed hotspot in GridDhtPartitionTopologyImpl caused by excessive HashSet allocations from "nodes(int, AffinityTopologyVersion)" method.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/f3e9ae40 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/f3e9ae40 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/f3e9ae40 Branch: refs/heads/ignite-1786 Commit: f3e9ae40d31ebe2bd7c338fa2ec6b9c72fe88c31 Parents: 532b373 Author: vozerov-gridgain <[email protected]> Authored: Fri Feb 5 12:23:33 2016 +0300 Committer: vozerov-gridgain <[email protected]> Committed: Fri Feb 5 12:23:33 2016 +0300 ---------------------------------------------------------------------- .../affinity/GridAffinityAssignment.java | 36 +++++++++++++++++++- .../affinity/GridAffinityAssignmentCache.java | 2 +- .../cache/GridCacheAffinityManager.java | 30 +++++++++++++--- .../dht/GridDhtPartitionTopologyImpl.java | 9 +++-- 4 files changed, 67 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/f3e9ae40/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityAssignment.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityAssignment.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityAssignment.java index 810843c..7b2bea3 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityAssignment.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityAssignment.java @@ -18,6 +18,7 @@ package org.apache.ignite.internal.processors.affinity; import java.io.Serializable; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -31,7 +32,7 @@ import org.apache.ignite.internal.util.typedef.internal.S; /** * Cached affinity calculations. */ -class GridAffinityAssignment implements Serializable { +public class GridAffinityAssignment implements Serializable { /** */ private static final long serialVersionUID = 0L; @@ -47,6 +48,9 @@ class GridAffinityAssignment implements Serializable { /** Map of backup node partitions. */ private final Map<UUID, Set<Integer>> backup; + /** Assignment node IDs */ + private transient volatile List<HashSet<UUID>> assignmentIds; + /** * Constructs cached affinity calculations item. * @@ -112,6 +116,36 @@ class GridAffinityAssignment implements Serializable { } /** + * Get affinity node IDs for partition. + * + * @param part Partition. + * @return Affinity nodes IDs. + */ + public HashSet<UUID> getIds(int part) { + assert part >= 0 && part < assignment.size() : "Affinity partition is out of range" + + " [part=" + part + ", partitions=" + assignment.size() + ']'; + + List<HashSet<UUID>> assignmentIds0 = assignmentIds; + + if (assignmentIds0 == null) { + assignmentIds0 = new ArrayList<>(); + + for (List<ClusterNode> assignmentPart : assignment) { + HashSet<UUID> partIds = new HashSet<>(); + + for (ClusterNode node : assignmentPart) + partIds.add(node.id()); + + assignmentIds0.add(partIds); + } + + assignmentIds = assignmentIds0; + } + + return assignmentIds0.get(part); + } + + /** * Get primary partitions for specified node ID. * * @param nodeId Node ID to get primary partitions for. http://git-wip-us.apache.org/repos/asf/ignite/blob/f3e9ae40/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityAssignmentCache.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityAssignmentCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityAssignmentCache.java index d728927..26e4d98 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityAssignmentCache.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityAssignmentCache.java @@ -428,7 +428,7 @@ public class GridAffinityAssignmentCache { * @param topVer Topology version. * @return Cached affinity. */ - private GridAffinityAssignment cachedAffinity(AffinityTopologyVersion topVer) { + public GridAffinityAssignment cachedAffinity(AffinityTopologyVersion topVer) { if (topVer.equals(AffinityTopologyVersion.NONE)) topVer = lastVersion(); else http://git-wip-us.apache.org/repos/asf/ignite/blob/f3e9ae40/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java index 375219a..21975da 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java @@ -17,11 +17,6 @@ package org.apache.ignite.internal.processors.cache; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.UUID; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteException; import org.apache.ignite.cluster.ClusterNode; @@ -29,6 +24,7 @@ import org.apache.ignite.events.DiscoveryEvent; import org.apache.ignite.internal.IgniteClientDisconnectedCheckedException; import org.apache.ignite.internal.IgniteInternalFuture; import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion; +import org.apache.ignite.internal.processors.affinity.GridAffinityAssignment; import org.apache.ignite.internal.processors.affinity.GridAffinityAssignmentCache; import org.apache.ignite.internal.util.GridLeanSet; import org.apache.ignite.internal.util.future.GridFinishedFuture; @@ -36,6 +32,12 @@ import org.apache.ignite.internal.util.typedef.F; import org.apache.ignite.lang.IgniteFuture; import org.jetbrains.annotations.Nullable; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.UUID; + /** * Cache affinity manager. */ @@ -246,6 +248,24 @@ public class GridCacheAffinityManager extends GridCacheManagerAdapter { } /** + * Get affinity assignment for the given topology version. + * + * @param topVer Toplogy version. + * @return Affinity affignment. + */ + public GridAffinityAssignment assignment(AffinityTopologyVersion topVer) { + if (cctx.isLocal()) + topVer = new AffinityTopologyVersion(1); + + GridAffinityAssignmentCache aff0 = aff; + + if (aff0 == null) + throw new IgniteException(FAILED_TO_FIND_CACHE_ERR_MSG + cctx.name()); + + return aff0.cachedAffinity(topVer); + } + + /** * @param key Key to check. * @param topVer Topology version. * @return Primary node for given key. http://git-wip-us.apache.org/repos/asf/ignite/blob/f3e9ae40/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java index 2ab8a12..d6fc8f1 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java @@ -36,6 +36,7 @@ import org.apache.ignite.cluster.ClusterNode; import org.apache.ignite.events.DiscoveryEvent; import org.apache.ignite.internal.IgniteInterruptedCheckedException; import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion; +import org.apache.ignite.internal.processors.affinity.GridAffinityAssignment; import org.apache.ignite.internal.processors.cache.GridCacheContext; import org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionExchangeId; import org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionFullMap; @@ -693,7 +694,9 @@ class GridDhtPartitionTopologyImpl implements GridDhtPartitionTopology { /** {@inheritDoc} */ @Override public Collection<ClusterNode> nodes(int p, AffinityTopologyVersion topVer) { - Collection<ClusterNode> affNodes = cctx.affinity().nodes(p, topVer); + GridAffinityAssignment affAssignment = cctx.affinity().assignment(topVer); + + Collection<ClusterNode> affNodes = affAssignment.get(p); lock.readLock().lock(); @@ -708,9 +711,9 @@ class GridDhtPartitionTopologyImpl implements GridDhtPartitionTopology { Collection<UUID> nodeIds = part2node.get(p); if (!F.isEmpty(nodeIds)) { - Collection<UUID> affIds = new HashSet<>(F.viewReadOnly(affNodes, F.node2id())); - for (UUID nodeId : nodeIds) { + HashSet<UUID> affIds = affAssignment.getIds(p); + if (!affIds.contains(nodeId) && hasState(p, nodeId, OWNING, MOVING, RENTING)) { ClusterNode n = cctx.discovery().node(nodeId);
