Reduce allocations on DefaultHeaders::containsValue#15843
Conversation
|
And I believe that or based on the type of Another GC pain point is re trimming which could just skip whitespaces; to be fair I hope this won't be a problem because I expect "old" browsers to just provide
which should not allocate any trimmed value or subsequence - and that's why i didn't implemented it here. |
5431f24 to
48bd450
Compare
|
FYI @isaacrivriv ^^ |
48bd450 to
691bf6d
Compare
| * Default implementation of {@link HttpHeaders}. | ||
| */ | ||
| public class DefaultHttpHeaders extends HttpHeaders { | ||
| private static final BiPredicate<CharSequence, CharSequence> CASE_INSENSITIVE_CONTAINS = |
There was a problem hiding this comment.
This is bimorphic on purpose, but clearly...it can become problematic if the containsAny method become too big to be inlined - and the predicate call site bloated of types.
But to be fair it shouldn't happen: this method here is used mostly with a single lambda type.
| * @param predicateArg argument passed as the second parameter to {@code valuePredicate} (may be {@code null}) | ||
| * @param valuePredicate predicate used to test stored header values (must not be {@code null}) | ||
| */ | ||
| public boolean containsAny(K name, V predicateArg, BiPredicate<? super V, ? super V> valuePredicate) { |
There was a problem hiding this comment.
This pattern comes from the old Disruptor times, to avoid allocations and defining different capturing lambda types based on the argument
|
I've added 2 benchmarks for existent values and not existent ones, getting mixed results vs before... vs before: The |
|
I've fixed the benchmark, because the lambda wasn't inlined because of the inlining depth (DOH!), and numbers now look more similar with some small win and loss This PR: whilst, before: In short, the performance looks here as expected, mostly unchanged (we reduced the allocation rate, a bit). |
|
I see a test failure, so handling it i.e. |
|
I've fixed the test failure: combiner http headers was relying on This is a case where OOP failed me: there's no way to remember to child impls of Performance wise, I have added a case which shows what happen (in some artificial way, I know) if the value iterator would escape and get allocated. This PR: whilst before: The results of this PR with garbage are the same, and I didn't reported them for brevity. |
c0bbbbd to
a94b4c2
Compare
|
@franz1981 please fix check style. |
Motivation: DefaultHeaders::containsValue is used heavily to detect if a request contains close or keep-alive header values, but the default implementations always allocates iterators Modification: Implements a specialized garbage-free method using optimized predicates which don't need to allocate any iterator Result: cheaper HTTP keep alive checks
a94b4c2 to
164e7f1
Compare
|
@franz1981 is this ready to go ? |
chrisvest
left a comment
There was a problem hiding this comment.
Just noticed one more interesting test case we could add. Otherwise looks good.
…Test.java Co-authored-by: Chris Vest <mr.chrisvest@gmail.com>
Motivation: DefaultHeaders::containsValue is used heavily to detect if a request contains close or keep-alive header values, but the default implementations always allocates iterators Modification: Implements a specialized garbage-free method using optimized predicates which don't need to allocate any iterator Result: cheaper HTTP keep alive checks --------- Co-authored-by: Norman Maurer <norman_maurer@apple.com> Co-authored-by: Chris Vest <mr.chrisvest@gmail.com> Co-authored-by: Chris Vest <christianvest_hansen@apple.com> (cherry picked from commit 874c995)
|
Thanks, @franz1981 ! |
Motivation: DefaultHeaders::containsValue is used heavily to detect if a request contains close or keep-alive header values, but the default implementations always allocates iterators Modification: Implements a specialized garbage-free method using optimized predicates which don't need to allocate any iterator Result: cheaper HTTP keep alive checks (cherry picked from commit 874c995) Co-authored-by: Francesco Nigro <nigro.fra@gmail.com> Co-authored-by: Norman Maurer <norman_maurer@apple.com>
Motivation: DefaultHeaders::containsValue is used heavily to detect if a request contains close or keep-alive header values, but the default implementations always allocates iterators Modification: Implements a specialized garbage-free method using optimized predicates which don't need to allocate any iterator Result: cheaper HTTP keep alive checks --------- Co-authored-by: Norman Maurer <norman_maurer@apple.com> Co-authored-by: Chris Vest <mr.chrisvest@gmail.com> Co-authored-by: Chris Vest <christianvest_hansen@apple.com>


Motivation:
DefaultHeaders::containsValue is used heavily to detect if a request contains close or keep-alive header values, but the default implementations always allocates iterators
Modification:
Implements a specialized garbage-free method using optimized predicates which don't need to allocate any iterator
Result:
cheaper HTTP keep alive checks