-
Notifications
You must be signed in to change notification settings - Fork 25.6k
Make some Allocation Decider Code a Little More JIT Aware #62275
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
e53fbf0
ad98bd5
99019b3
6e772a0
7ef2fc7
1f811c8
6bd6608
8a59791
89bc2c6
7813daf
765850c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,6 +23,7 @@ | |
|
|
||
| import org.apache.logging.log4j.LogManager; | ||
| import org.apache.logging.log4j.Logger; | ||
| import org.elasticsearch.cluster.routing.RoutingNodes; | ||
| import org.elasticsearch.cluster.routing.ShardRouting; | ||
| import org.elasticsearch.cluster.routing.allocation.RoutingAllocation; | ||
| import org.elasticsearch.common.settings.ClusterSettings; | ||
|
|
@@ -109,40 +110,53 @@ public Decision canRebalance(ShardRouting shardRouting, RoutingAllocation alloca | |
| return canRebalance(allocation); | ||
| } | ||
|
|
||
| private static final Decision YES_ALL_PRIMARIES_ACTIVE = Decision.single(Decision.Type.YES, NAME, "all primary shards are active"); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be nice to add
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, I'm starting to wonder how much point there even is in making the
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ++, seems just resolving this early is not a big deal. It will resolve it anyway in both equals, hashCode and streaming write.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perfect :) Made it eager serialize now, also makes the |
||
|
|
||
| private static final Decision YES_ALL_SHARDS_ACTIVE = Decision.single(Decision.Type.YES, NAME, "all shards are active"); | ||
|
|
||
| private static final Decision NO_UNASSIGNED_PRIMARIES = Decision.single(Decision.Type.NO, NAME, | ||
| "the cluster has unassigned primary shards and cluster setting [" | ||
| + CLUSTER_ROUTING_ALLOCATION_ALLOW_REBALANCE + "] is set to [" + ClusterRebalanceType.INDICES_PRIMARIES_ACTIVE + "]"); | ||
|
|
||
| private static final Decision NO_INACTIVE_PRIMARIES = Decision.single(Decision.Type.NO, NAME, | ||
| "the cluster has inactive primary shards and cluster setting [" + CLUSTER_ROUTING_ALLOCATION_ALLOW_REBALANCE + | ||
| "] is set to [" + ClusterRebalanceType.INDICES_PRIMARIES_ACTIVE + "]"); | ||
|
|
||
| private static final Decision NO_UNASSIGNED_SHARDS = Decision.single(Decision.Type.NO, NAME, | ||
| "the cluster has unassigned shards and cluster setting [" + CLUSTER_ROUTING_ALLOCATION_ALLOW_REBALANCE + | ||
| "] is set to [" + ClusterRebalanceType.INDICES_ALL_ACTIVE + "]"); | ||
|
|
||
| private static final Decision NO_INACTIVE_SHARDS = Decision.single(Decision.Type.NO, NAME, | ||
| "the cluster has inactive shards and cluster setting [" + CLUSTER_ROUTING_ALLOCATION_ALLOW_REBALANCE + | ||
| "] is set to [" + ClusterRebalanceType.INDICES_ALL_ACTIVE + "]"); | ||
|
|
||
| @Override | ||
| public Decision canRebalance(RoutingAllocation allocation) { | ||
| if (type == ClusterRebalanceType.INDICES_PRIMARIES_ACTIVE) { | ||
| // check if there are unassigned primaries. | ||
| if ( allocation.routingNodes().hasUnassignedPrimaries() ) { | ||
| return allocation.decision(Decision.NO, NAME, | ||
| "the cluster has unassigned primary shards and cluster setting [%s] is set to [%s]", | ||
| CLUSTER_ROUTING_ALLOCATION_ALLOW_REBALANCE, type); | ||
| } | ||
| // check if there are initializing primaries that don't have a relocatingNodeId entry. | ||
| if ( allocation.routingNodes().hasInactivePrimaries() ) { | ||
| return allocation.decision(Decision.NO, NAME, | ||
| "the cluster has inactive primary shards and cluster setting [%s] is set to [%s]", | ||
| CLUSTER_ROUTING_ALLOCATION_ALLOW_REBALANCE, type); | ||
| } | ||
|
|
||
| return allocation.decision(Decision.YES, NAME, "all primary shards are active"); | ||
| } | ||
| if (type == ClusterRebalanceType.INDICES_ALL_ACTIVE) { | ||
| // check if there are unassigned shards. | ||
| if (allocation.routingNodes().hasUnassignedShards() ) { | ||
| return allocation.decision(Decision.NO, NAME, | ||
| "the cluster has unassigned shards and cluster setting [%s] is set to [%s]", | ||
| CLUSTER_ROUTING_ALLOCATION_ALLOW_REBALANCE, type); | ||
| } | ||
| // in case all indices are assigned, are there initializing shards which | ||
| // are not relocating? | ||
| if ( allocation.routingNodes().hasInactiveShards() ) { | ||
| return allocation.decision(Decision.NO, NAME, | ||
| "the cluster has inactive shards and cluster setting [%s] is set to [%s]", | ||
| CLUSTER_ROUTING_ALLOCATION_ALLOW_REBALANCE, type); | ||
| } | ||
| final boolean debug = allocation.debugDecision(); | ||
| final RoutingNodes routingNodes = allocation.routingNodes(); | ||
| switch (type) { | ||
| case INDICES_PRIMARIES_ACTIVE: | ||
| // check if there are unassigned primaries. | ||
| if (routingNodes.hasUnassignedPrimaries()) { | ||
| return debug ? NO_UNASSIGNED_PRIMARIES : Decision.NO; | ||
|
||
| } | ||
| // check if there are initializing primaries that don't have a relocatingNodeId entry. | ||
| if (routingNodes.hasInactivePrimaries()) { | ||
| return debug ? NO_INACTIVE_PRIMARIES : Decision.NO; | ||
| } | ||
| return debug ? YES_ALL_PRIMARIES_ACTIVE : Decision.YES; | ||
| case INDICES_ALL_ACTIVE: | ||
| // check if there are unassigned shards. | ||
| if (routingNodes.hasUnassignedShards()) { | ||
| return debug ? NO_UNASSIGNED_SHARDS : Decision.NO; | ||
| } | ||
| // in case all indices are assigned, are there initializing shards which | ||
| // are not relocating? | ||
| if (routingNodes.hasInactiveShards()) { | ||
| return debug ? NO_INACTIVE_SHARDS : Decision.NO; | ||
| } | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add
to signal that fall through is intended. |
||
| // type == Type.ALWAYS | ||
| return allocation.decision(Decision.YES, NAME, "all shards are active"); | ||
| // all shards active from above or type == Type.ALWAYS | ||
|
||
| return debug ? YES_ALL_SHARDS_ACTIVE : Decision.YES; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -41,27 +41,36 @@ public class MaxRetryAllocationDecider extends AllocationDecider { | |
|
|
||
| public static final String NAME = "max_retry"; | ||
|
|
||
| private static final Decision YES_NO_FAILURES = Decision.single(Decision.Type.YES, NAME, "shard has no previous failures"); | ||
|
|
||
| @Override | ||
| public Decision canAllocate(ShardRouting shardRouting, RoutingAllocation allocation) { | ||
| final UnassignedInfo unassignedInfo = shardRouting.unassignedInfo(); | ||
| final Decision decision; | ||
| if (unassignedInfo != null && unassignedInfo.getNumFailedAllocations() > 0) { | ||
| final boolean debug = allocation.debugDecision(); | ||
| final int numFailedAllocations = unassignedInfo == null ? 0 : unassignedInfo.getNumFailedAllocations(); | ||
| if (numFailedAllocations > 0) { | ||
| final IndexMetadata indexMetadata = allocation.metadata().getIndexSafe(shardRouting.index()); | ||
|
||
| final int maxRetry = SETTING_ALLOCATION_MAX_RETRY.get(indexMetadata.getSettings()); | ||
| if (unassignedInfo.getNumFailedAllocations() >= maxRetry) { | ||
| decision = allocation.decision(Decision.NO, NAME, "shard has exceeded the maximum number of retries [%d] on " + | ||
| "failed allocation attempts - manually call [/_cluster/reroute?retry_failed=true] to retry, [%s]", | ||
| maxRetry, unassignedInfo.toString()); | ||
| } else { | ||
| decision = allocation.decision(Decision.YES, NAME, "shard has failed allocating [%d] times but [%d] retries are allowed", | ||
| unassignedInfo.getNumFailedAllocations(), maxRetry); | ||
| } | ||
| final Decision res = numFailedAllocations >= maxRetry ? Decision.NO : Decision.YES; | ||
| decision = debug ? debugDecision(res, unassignedInfo, numFailedAllocations, maxRetry) : res; | ||
|
||
| } else { | ||
| decision = allocation.decision(Decision.YES, NAME, "shard has no previous failures"); | ||
| decision = debug ? YES_NO_FAILURES : Decision.YES; | ||
|
||
| } | ||
| return decision; | ||
| } | ||
|
|
||
| private static Decision debugDecision(Decision decision, UnassignedInfo unassignedInfo, int numFailedAllocations, int maxRetry) { | ||
| if (decision.type() == Decision.Type.YES) { | ||
| return Decision.single(Decision.Type.NO, NAME, "shard has exceeded the maximum number of retries [%d] on " + | ||
| "failed allocation attempts - manually call [/_cluster/reroute?retry_failed=true] to retry, [%s]", | ||
| maxRetry, unassignedInfo.toString()); | ||
| } else { | ||
| return Decision.single(Decision.Type.YES, NAME, "shard has failed allocating [%d] times but [%d] retries are allowed", | ||
| numFailedAllocations, maxRetry); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public Decision canAllocate(ShardRouting shardRouting, RoutingNode node, RoutingAllocation allocation) { | ||
| return canAllocate(shardRouting, allocation); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason for not using
[%s]for the settings key?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I figured if we're already optimizing, why not just make this compile to one string constant instead of a constant format replacement
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, it just seems odd to have both forms (string concatenation and replacement) in the very same line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm replacement with a constant seems odd as well to me as well :) But I just realized that this is the debug path anyway, so I'm happy to change this back if you want.
That said, for better or for worse, we do have that pattern of mixing concatenation + replacement in a bunch of places for logging or for file name formatting in
BlobstoreRepositoryfor example?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, leave it as is, I can certainly gladly accept it as is, was a small nit only.
I think the
getKeycall prevents that? Though maybe the jit does something smart about this?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have thought the JIT can figure this out, but it took only a few minutes with JitWatch to learn that this is not the case. This initially compiles to:
and all that happens is that the
getKeycall is eventually inlined but the string concatenation still happens every time.-> I'll revert this before merging in a bit :)