Only update response headers if we have a new one (#37590)

Currently when adding a response header, we do some de-duplication, and
maybe drop the header on the floor if we have reached capacity. Yet, we
still update the thread local tracking the response headers. This is
really expensive because under the hood there is a shared reference that
we synchronize on. In the case of a request processed across many shards
in a tight loop, this contention can be detrimental to performance. We
can avoid updating the thread local in these cases though, when the
response header is duplicate of one that we have already seen, or when
it's dropped on the floor. This commit addresses these performance
issues by avoiding the unnecessary set.
This commit is contained in:
Jason Tedor 2019-01-18 08:20:05 -05:00 committed by GitHub
parent 3a96608b3f
commit ed297b7369
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 11 additions and 1 deletions

View File

@ -323,7 +323,17 @@ public final class ThreadContext implements Closeable, Writeable {
* @param uniqueValue the function that produces de-duplication values
*/
public void addResponseHeader(final String key, final String value, final Function<String, String> uniqueValue) {
threadLocal.set(threadLocal.get().putResponse(key, value, uniqueValue, maxWarningHeaderCount, maxWarningHeaderSize));
/*
* Updating the thread local is expensive due to a shared reference that we synchronize on, so we should only do it if the thread
* context struct changed. It will not change if we de-duplicate this value to an existing one, or if we don't add a new one because
* we have reached capacity.
*/
final ThreadContextStruct current = threadLocal.get();
final ThreadContextStruct maybeNext =
current.putResponse(key, value, uniqueValue, maxWarningHeaderCount, maxWarningHeaderSize);
if (current != maybeNext) {
threadLocal.set(maybeNext);
}
}
/**