Skip to content
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

Streamline AsyncShardFetch#getNumberOfInFlightFetches #93632

Merged
merged 8 commits into from
Feb 13, 2023

Conversation

luyuncheng
Copy link
Contributor

@luyuncheng luyuncheng commented Feb 9, 2023

When we restart a ES 7.10 cluster, we found lead master cpu hot_threads much cost in org.elasticsearch.action.admin.cluster.health.TransportClusterHealthAction.getResponse -> org.elasticsearch.cluster.routing.allocation.AllocationService.getNumberOfInFlightFetches

image

we trace the function getNumberOfInFlightFetches

80940a22-3935-408d-a967-c4b98cd98165

it shows that all time cost in GatewayAllocator.getNumberOfInFlightFetches ,

public int getNumberOfInFlightFetches() {
int count = 0;
for (AsyncShardFetch<NodeGatewayStartedShards> fetch : asyncFetchStarted.values()) {
count += fetch.getNumberOfInFlightFetches();
}
for (AsyncShardFetch<NodeStoreFilesMetadata> fetch : asyncFetchStore.values()) {
count += fetch.getNumberOfInFlightFetches();
}
return count;

In some case, it will scan all shards * ndoes every time.

public synchronized int getNumberOfInFlightFetches() {
int count = 0;
for (NodeEntry<T> nodeEntry : cache.values()) {
if (nodeEntry.isFetching()) {
count++;
}
}
return count;

BUT, in most cases, the fetching status is all false after scanned once.
there is no need to iterator nodes every time. we can add a fetching cache to ignore this at this PR

08a8984c-5268-41c6-a002-c328737e5a08

ISSUE: #93631

@elasticsearchmachine elasticsearchmachine added needs:triage Requires assignment of a team area label v8.8.0 external-contributor Pull request authored by a developer outside the Elasticsearch team labels Feb 9, 2023
@DaveCTurner DaveCTurner added >bug :Distributed/Allocation All issues relating to the decision making around placing a shard (both master logic & on the nodes) and removed needs:triage Requires assignment of a team area label labels Feb 10, 2023
@elasticsearchmachine elasticsearchmachine added the Team:Distributed Meta label for distributed team label Feb 10, 2023
@elasticsearchmachine
Copy link
Collaborator

Pinging @elastic/es-distributed (Team:Distributed)

@DaveCTurner DaveCTurner self-assigned this Feb 10, 2023
@DaveCTurner
Copy link
Contributor

@elasticmachine generate changelog

@DaveCTurner
Copy link
Contributor

Thanks @luyuncheng for spotting this and suggesting a fix. I think there's a better approach, however: we can make it so that getNumberOfInFlightFetches (and hasAnyNodeFetching) don't need to iterate at all. Instead, we can track the number of in-flight fetches directly in another field, adjusting the field when calling any of the methods that adjust NodeEntry#fetching and when adding or removing entries from AsyncShardFetch#cache. Would you try doing that?

@luyuncheng
Copy link
Contributor Author

Thanks @luyuncheng for spotting this and suggesting a fix. I think there's a better approach, however: we can make it so that getNumberOfInFlightFetches (and hasAnyNodeFetching) don't need to iterate at all. Instead, we can track the number of in-flight fetches directly in another field, adjusting the field when calling any of the methods that adjust NodeEntry#fetching and when adding or removing entries from AsyncShardFetch#cache. Would you try doing that?

LGTM, Let me try.

@luyuncheng
Copy link
Contributor Author

we can track the number of in-flight fetches directly in another field

@DaveCTurner at commit 6080f60
i try to add a field fetchingCount tracking the number of in-flight fetches, and it can remove the iterator from getNumberOfInFlightFetches and hasAnyNodeFetching

Copy link
Contributor

@DaveCTurner DaveCTurner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. I left a few small comments.

I'd also like to introduce a method to verify that the count is consistent when not running in prod:

private boolean assertFetchingCountConsistent() {
    assert Thread.holdsLock(this);
    assert fetchingCount.get() == cache.values().stream().filter(NodeEntry::isFetching).count();
    return true;
}

and then we can say assert assertFetchingCountConsistent(); after we've changed the cache contents. That way we should pick up any mistakes in this area quickly.

}
return count;
public int getNumberOfInFlightFetches() {
return fetchingCount.get();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Much nicer 😄

@@ -57,6 +58,7 @@
private final Set<String> nodesToIgnore = new HashSet<>();
private final AtomicLong round = new AtomicLong();
private boolean closed;
private final AtomicInteger fetchingCount = new AtomicInteger();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this could just be a volatile int because it's only ever updated within synchronized methods.

}
}
return false;
// visible for testing
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm ok with keeping this private, I don't think it needs testing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

++ modified

@DaveCTurner DaveCTurner changed the title Reduce getNumberOfInFlightFetches iterator in ClusterHealthAction of AllocationService Streamline AsyncShardFetch#getNumberOfInFlightFetches Feb 10, 2023
@DaveCTurner
Copy link
Contributor

I have pushed a commit (5beddb8) which adds the required changelog YAML file. You'll need to pull this branch and merge or rebase your changes on top of my commit.

@DaveCTurner
Copy link
Contributor

@elasticmachine ok to test

Copy link
Contributor

@DaveCTurner DaveCTurner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks @luyuncheng

@DaveCTurner
Copy link
Contributor

(it's Friday evening here, I will not merge this before Monday)

@DaveCTurner DaveCTurner merged commit 8cd7170 into elastic:main Feb 13, 2023
salvatore-campagna pushed a commit to salvatore-campagna/elasticsearch that referenced this pull request Feb 16, 2023
Avoids an O(#nodes) iteration by tracking the number of fetches directly.
saarikabhasi pushed a commit to saarikabhasi/elasticsearch that referenced this pull request Apr 10, 2023
Avoids an O(#nodes) iteration by tracking the number of fetches directly.
DaveCTurner pushed a commit to DaveCTurner/elasticsearch that referenced this pull request Jun 5, 2023
Avoids an O(#nodes) iteration by tracking the number of fetches directly.

Backport of elastic#93632 to 7.17
DaveCTurner added a commit that referenced this pull request Jun 5, 2023
Avoids an O(#nodes) iteration by tracking the number of fetches directly.

Backport of #93632 to 7.17

Co-authored-by: luyuncheng <luyuncheng@bytedance.com>
DaveCTurner added a commit to DaveCTurner/elasticsearch that referenced this pull request Jun 5, 2023
DaveCTurner added a commit to DaveCTurner/elasticsearch that referenced this pull request Jun 5, 2023
DaveCTurner added a commit to DaveCTurner/elasticsearch that referenced this pull request Jun 5, 2023
HiDAl pushed a commit to HiDAl/elasticsearch that referenced this pull request Jun 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
>bug :Distributed/Allocation All issues relating to the decision making around placing a shard (both master logic & on the nodes) external-contributor Pull request authored by a developer outside the Elasticsearch team Team:Distributed Meta label for distributed team v8.8.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants