Skip to content

Serialize Get Mappings Response on Generic ThreadPool#57937

Merged
original-brownbear merged 2 commits intoelastic:masterfrom
original-brownbear:run-get-mapping-rest-on-generic
Aug 21, 2020
Merged

Serialize Get Mappings Response on Generic ThreadPool#57937
original-brownbear merged 2 commits intoelastic:masterfrom
original-brownbear:run-get-mapping-rest-on-generic

Conversation

@original-brownbear
Copy link
Copy Markdown
Contributor

@original-brownbear original-brownbear commented Jun 10, 2020

Solves/mitigates the issue observed in #57284

For large responses to the get mappings request, the serialization
to XContent can be extremely slow (serializing mappings is expensive since
we have to decompress and deserialize the mapping source).
To not introduce instability on the IO thread handling the get mappings response
we should move the serialization to the generic pool.
The trade-off of introducing one or two new context switches for responses that are
small enough to not cause trouble on the transport thread to prevent instability
in case of a large number of mappings in the cluster seems worth it.

Marking this team discuss for now, since we had the larger discussion of where REST actions should execute before and didn't come to a conclusion here yet. While this is a special case, we have a number of other potentially slow REST actions like this one where a very large response gets serialized.

For large responses to the get mappings request, the serialization
to XContent can be extremely slow (serializing mappings is expensive since
we have to decompress and deserialize the mapping source).
To not introduce instability on the IO thread handling the get mappings response
we should move the serialization to the generic pool.
The trade-off of introducing one or two new context switches for responses that are
small enough to not cause trouble on the transport thread to prevent instability
in case of a large number of mappings in the cluster seems worth it.
@original-brownbear original-brownbear added :Distributed/Network Http and internode communication implementations team-discuss labels Jun 10, 2020
@elasticmachine
Copy link
Copy Markdown
Collaborator

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

@fcofdez
Copy link
Copy Markdown
Contributor

fcofdez commented Jun 10, 2020

I wonder if it would make sense to add a new method to TransportMasterNodeAction so we can define in which executor the response would be processed and inject that in the ActionListenerResponseHandler that's passed to the transportService. wdyt @original-brownbear ?

@original-brownbear
Copy link
Copy Markdown
Contributor Author

I wonder if it would make sense to add a new method to TransportMasterNodeAction

Not sure that's necessarily where we'd want to add this given how we already have infrastructure like ThreadedActionListener that could be used for this kind of thing. But yea, that's why I added >team discuss, maybe we can see enough spots to make it so we want to generalize something (for the REST layer I guess) here.

@original-brownbear
Copy link
Copy Markdown
Contributor Author

We discussed this during team discuss and decided to check if slowness in this API call happens on Cloud at any non-trivial rate.

I investigated this on Cloud and we have a lot of slow get mappings responses (up to minutes in response time) so we should take action here I think.

Copy link
Copy Markdown
Member

@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.

I'd rather not use the generic pool for this, but MANAGEMENT seems like a reasonable option. See inline comment about a timeout.

// on an IO thread
threadPool.generic().execute(ActionRunnable.wrap(this, l -> new RestBuilderListener<GetMappingsResponse>(channel) {
@Override
public RestResponse buildResponse(final GetMappingsResponse response, final XContentBuilder builder) throws Exception {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

WDYT about checking for a timeout again here before we do all the serialisation work? If we use a bounded threadpool then these things might pile up, so aborting early might be a helpful way to push back.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

👍 how about 0bd68d4 ? :)

@original-brownbear
Copy link
Copy Markdown
Contributor Author

Jenkins run elasticsearch-ci/packaging-sample-windows

Copy link
Copy Markdown
Member

@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

@original-brownbear
Copy link
Copy Markdown
Contributor Author

Thanks David!

@original-brownbear original-brownbear merged commit e5eca6a into elastic:master Aug 21, 2020
@original-brownbear original-brownbear deleted the run-get-mapping-rest-on-generic branch August 21, 2020 05:12
original-brownbear added a commit that referenced this pull request Aug 21, 2020
For large responses to the get mappings request, the serialization
to XContent can be extremely slow (serializing mappings is expensive since
we have to decompress and deserialize the mapping source).
To not introduce instability on the IO thread handling the get mappings response
we should move the serialization to the management pool.
The trade-off of introducing one or two new context switches for responses that are
small enough to not cause trouble on the transport thread to prevent instability
in case of a large number of mappings in the cluster seems worth it.
original-brownbear added a commit that referenced this pull request Sep 28, 2020
…62753)

Currently, `finishHim` can either execute on the specified executor
(in the less likely case that the local node request is the last to arrive)
or on a transport thread.
In case of e.g. `org.elasticsearch.action.admin.cluster.stats.TransportClusterStatsAction`
this leads to an expensive execution that deserializes all mapping metadata in the cluster
running on the transport thread and destabilizing the cluster. In case of this transport
action it was specifically moved to the `MANAGEMENT` thread to avoid the high cost of processing
the stats requests on the nodes during fan-out but that did not cover the final execution
on the node that received the initial request. This PR  adds to ability to optionally specify the executor for the final step of the
nodes request execution and uses that to work around the issue for the slow `TransportClusterStatsAction`.

Note: the specific problem that motivated this PR is essentially the same as #57937 where we moved the execution off the transport and on the management thread as a fix as well.
original-brownbear added a commit that referenced this pull request Sep 28, 2020
…62753) (#62955)

Currently, `finishHim` can either execute on the specified executor
(in the less likely case that the local node request is the last to arrive)
or on a transport thread.
In case of e.g. `org.elasticsearch.action.admin.cluster.stats.TransportClusterStatsAction`
this leads to an expensive execution that deserializes all mapping metadata in the cluster
running on the transport thread and destabilizing the cluster. In case of this transport
action it was specifically moved to the `MANAGEMENT` thread to avoid the high cost of processing
the stats requests on the nodes during fan-out but that did not cover the final execution
on the node that received the initial request. This PR  adds to ability to optionally specify the executor for the final step of the
nodes request execution and uses that to work around the issue for the slow `TransportClusterStatsAction`.

Note: the specific problem that motivated this PR is essentially the same as #57937 where we moved the execution off the transport and on the management thread as a fix as well.
original-brownbear added a commit that referenced this pull request Dec 4, 2020
…#65843)

Moving the cluster state response serialization to the management thread just like we did for the mappings response in #57937 since it's a potentially very large and slow to serialize response.
original-brownbear added a commit that referenced this pull request Dec 4, 2020
…#65843) (#65881)

Moving the cluster state response serialization to the management thread just like we did for the mappings response in #57937 since it's a potentially very large and slow to serialize response.
@original-brownbear original-brownbear restored the run-get-mapping-rest-on-generic branch December 6, 2020 19:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

:Distributed/Network Http and internode communication implementations >non-issue Team:Distributed Meta label for distributed team. v7.10.0 v8.0.0-alpha1

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants