-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Issue #4861 - reduce garbage created by the async request attributes #4867
Conversation
Signed-off-by: Lachlan Roberts <[email protected]>
public class ServletAttributes implements Attributes | ||
{ | ||
private final Attributes _attributes; | ||
|
||
public ServletAttributes() | ||
{ | ||
_attributes = new AsyncAttributes(new AttributesMap()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like all the dereferences here. We end up with ServletAttributes->AsyncAttributes->AttributesMap
, so 3 object and 3 dereferences.
I think it would be much better to do (also note the name change):
public class ServletAttributes implements Attributes | |
{ | |
private final Attributes _attributes; | |
public ServletAttributes() | |
{ | |
_attributes = new AsyncAttributes(new AttributesMap()); | |
} | |
public class AsyncAttributesMap extends AttributesMap | |
{ | |
public AsyncAttributesMap() | |
{ | |
} |
The override the methods as follows:
@Override
 public Object getAttribute(String name)
 {
// do the AsyncAttribute handling here
// else
return super.getAttribute(name);
}
Then you don't need AsyncAttributes class.
jetty-server/src/main/java/org/eclipse/jetty/server/AsyncAttributes.java
Show resolved
Hide resolved
jetty-server/src/main/java/org/eclipse/jetty/server/AsyncAttributes.java
Show resolved
Hide resolved
@@ -199,7 +200,7 @@ public static Request getBaseRequest(ServletRequest request) | |||
private boolean _handled = false; | |||
private boolean _contentParamsExtracted; | |||
private boolean _requestedSessionIdFromCookie = false; | |||
private Attributes _attributes; | |||
private Attributes _attributes = new ServletAttributes(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah we can't make this final because of possible wrappers that don't unwrap.
So go back to lazy creation of this field...... OR have 2 fields:
private Attributes _attributes = new ServletAttributes(); | |
private final AsyncAttributesMap _asyncAttributes = new AsyncAttributesMap(); | |
private Attributes _attributes = _asyncAttributes; |
This way, async could as the request directly for the _asyncAttributes
and set the fields on it.... but we'd still create an extra class with 6 fields even if we never use attributes.... hmmmm @lorban your thoughts on which is best?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would leave the _attributes
field non-final, this is the simplest way to go.
Any sort of cleanup seem to require a non-negligible amount of refactoring, so I'd keep #4861 open until the code is cleaned up. Regarding perf, this small change has 99% of the benefits of a larger refactoring.
Signed-off-by: Lachlan Roberts <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm approving, but there are a few niggles that I think you should change... but will not need rereview.
if (ServletAttributes.class.equals(_attributes.getClass())) | ||
_attributes.clearAttributes(); | ||
else | ||
_attributes = new ServletAttributes(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just reset to null
if (_asyncAttributes == null) | ||
_attributes.removeAttribute(name); | ||
else | ||
_asyncAttributes.removeAttribute(name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is clearer as:
if (_asyncAttributes == null) | |
_attributes.removeAttribute(name); | |
else | |
_asyncAttributes.removeAttribute(name); | |
(_asyncAttributes == null ? _asyncAttributes : _attributes).removeAttribute(name); |
or maybe even with a private method:
attributes().removeAttribute(name);
same for other methods below.
Signed-off-by: Lachlan Roberts <[email protected]>
Build failure is a StackOverflowError
|
Test failure in
|
A slightly different one of the last failure.
|
…ributesMap Signed-off-by: Lachlan Roberts <[email protected]>
Issue #4861
Reduce garbage produced by creating the
ConcurrentHashMap
ofAttributesMap
when going async. InRequest
we now useServletAttributes
as the intialAttributes
instance which can still be subsequently wrapped by forwards and includes, this will store the async mapping attributes as local variables instead of using theAttributesMap
.The
HttpServletMapping
needs to be added back toAsyncAttributes
when this is merged to 10.