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

Rally PMC performance regression due to compression #36399

Closed
Tim-Brooks opened this issue Dec 8, 2018 · 6 comments · Fixed by #36522
Closed

Rally PMC performance regression due to compression #36399

Tim-Brooks opened this issue Dec 8, 2018 · 6 comments · Fixed by #36522
Labels
discuss :Distributed/Network Http and internode communication implementations

Comments

@Tim-Brooks
Copy link
Contributor

Around early November we experienced a noticeable performance regression on the PMC track in our nightly benchmarks. This only applied to multi-node (network) workloads and was apparent on both the netty and nio runs.

This is very visible on the 90-day graph.

@dliappis identified that it was due to #35357. I investigated this and identified what the root cause is.

Individual actions in Elasticsearch can set compression to true in TransportRequestOptions.

TransportRequestOptions.Builder builder = TransportRequestOptions.*builder*();
builder.withCompress(true);
TransportRequestOptions options = builder.build();

A number of actions set this option manually:

  • TransportGetTaskAction - false
  • BulkAction - true
  • TransportNodesAction.AsyncAction - depends
  • TransportTasksAction - depends
  • PublishClusterStateAction - false
  • RemoteRecoveryTargetHandler - depends

Prior to #35357 this option had no effect. If it was set to false, TcpTransport would overwrite it if transport.tcp.compress was set to true.

if (compress) {
    options = TransportRequestOptions.builder(options).withCompress(true).build();
}

If it was set to true, TcpTransport would only respect it if transport.tcp.compress was also set to true.

private boolean canCompress(TransportRequest request) {
    return this.compress && (!(request instanceof BytesTransportRequest));
}

After #35357, we still overwrite false if compression is enabled based on settings. However, we incidentally started to respect true. So if compression was not enabled we would still compress if it was requested by the TransportRequestOptions.

private boolean canCompress(TransportRequest request) {
    return request instanceof BytesTransportRequest == false;
}

This one change led to the performance regression because the PMC benchmark probably uses messages that ask for compression. Our benchmarks set the compression setting to false. So these messages were not compressed before the change and are compressed after the change. Since the benchmarks (I think) have fast network connections, this compression likely increases CPU usage and the bandwidth savings are probably irrelevant.

This raises the question of what we want the behavior to be. The behavior prior to #35357 makes no sense as there was no point in the compression being set in the TransportRequestOptions.

Do we want:

  1. Compression is only used if both request and setting say true?
  2. Compression is used if either request or setting is true? This would overwrite false. This is equivalent to post-Move compression config to ConnectionProfile #35357 behavior.
  3. TransportRequestOptions be the primary choice and the setting be the fallback choice? This is tricky right now because TransportRequestOptions uses a boolean for the compression indicator. So we do not know if false was set or if it was not set.
  4. Remove compress from TransportRequestOptions and always compress based on the setting. This is equivalent to pre-Move compression config to ConnectionProfile #35357 behavior.

@jasontedor @s1monw

@Tim-Brooks Tim-Brooks added discuss :Distributed/Network Http and internode communication implementations labels Dec 8, 2018
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-distributed

@jasontedor
Copy link
Member

I think that we should only compress if transport.tcp.compress is enabled (or if a remote connection has compression enabled individually) and remove compression from transport request options (your fourth option). I don't think we should be handling any other requests specially (e.g., compression of segments). If we find that we need special compression on some requests, then we can consider adding settings for them in the future but this is not something that we should pursue without evidence of a need for it.

@Tim-Brooks
Copy link
Contributor Author

I think that we should only compress if transport.tcp.compress is enabled (or if a remote connection has compression enabled individually)

Yes to clarify, the "setting" means whichever compression setting applies based on the rules introduced in #35357 and outlined in #34483.

If @s1monw agrees, I can remove compression from the TransportRequestOptions in a PR this week.

@dliappis
Copy link
Contributor

dliappis commented Dec 9, 2018

Since the benchmarks (I think) have fast network connections, this compression likely increases CPU usage and the bandwidth savings are probably irrelevant.

Confirmed, the network connection between the benchmark machines is a dedicated 10Gbps link.

@s1monw
Copy link
Contributor

s1monw commented Dec 11, 2018

If @s1monw agrees, I can remove compression from the TransportRequestOptions in a PR this week.

+1

Tim-Brooks added a commit that referenced this issue Dec 12, 2018
Currently TransportRequestOptions allows specific requests to request
compression. This commit removes this and always compresses based on the
settings. Additionally, it removes TransportResponseOptions as they
are unused.

This closes #36399.
Tim-Brooks added a commit to Tim-Brooks/elasticsearch that referenced this issue Dec 12, 2018
Currently TransportRequestOptions allows specific requests to request
compression. This commit removes this and always compresses based on the
settings. Additionally, it removes TransportResponseOptions as they
are unused.

This closes elastic#36399.
Tim-Brooks added a commit that referenced this issue Dec 12, 2018
Currently TransportRequestOptions allows specific requests to request
compression. This commit removes this and always compresses based on the
settings. Additionally, it removes TransportResponseOptions as they
are unused.

This closes #36399.
@Tim-Brooks
Copy link
Contributor Author

Tim-Brooks commented Dec 13, 2018

After #36522 was merged, our PMC benchmarks reverted to their prior performance level.

Tim-Brooks added a commit to Tim-Brooks/elasticsearch that referenced this issue Dec 19, 2018
This is a follow-up to some discussions around elastic#36399. Currently we have
relatively confusing compression behavior where compression can be
configured for requests based on `transport.compress` or a specific
setting for a remote cluster. However, we can only compress responses
based on `transport.compress` as we do not know where a request is
coming from (currently).

This commit modifies the behavior to NEVER compress responses based on
settings. Instead, a response will only be compressed if the request was
compressed. This commit also updates the documentation to more clearly
described transport level compression.
Tim-Brooks added a commit that referenced this issue Dec 21, 2018
This is a follow-up to some discussions around #36399. Currently we have
relatively confusing compression behavior where compression can be
configured for requests based on transport.compress or a specific
setting for a remote cluster. However, we can only compress responses
based on transport.compress as we do not know where a request is
coming from (currently).

This commit modifies the behavior to NEVER compress responses based on
settings. Instead, a response will only be compressed if the request was
compressed. This commit also updates the documentation to more clearly
described transport level compression.
Tim-Brooks added a commit to Tim-Brooks/elasticsearch that referenced this issue Dec 21, 2018
This is a follow-up to some discussions around elastic#36399. Currently we have
relatively confusing compression behavior where compression can be
configured for requests based on transport.compress or a specific
setting for a remote cluster. However, we can only compress responses
based on transport.compress as we do not know where a request is
coming from (currently).

This commit modifies the behavior to NEVER compress responses based on
settings. Instead, a response will only be compressed if the request was
compressed. This commit also updates the documentation to more clearly
described transport level compression.
Tim-Brooks added a commit that referenced this issue Dec 22, 2018
This is a follow-up to some discussions around #36399. Currently we have
relatively confusing compression behavior where compression can be
configured for requests based on transport.compress or a specific
setting for a remote cluster. However, we can only compress responses
based on transport.compress as we do not know where a request is
coming from (currently).

This commit modifies the behavior to NEVER compress responses based on
settings. Instead, a response will only be compressed if the request was
compressed. This commit also updates the documentation to more clearly
described transport level compression.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discuss :Distributed/Network Http and internode communication implementations
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants