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

Remove unnecessary content type checks #37646

Merged
merged 1 commit into from Dec 11, 2023
Merged

Remove unnecessary content type checks #37646

merged 1 commit into from Dec 11, 2023

Conversation

geoand
Copy link
Contributor

@geoand geoand commented Dec 11, 2023

These checks have potentially already
been performed in ClassRoutingHandler

Closes: #37637

private static final String PRODUCES_CHECKED_PROPERTY_KEY = AbstractResteasyReactiveContext.CUSTOM_RR_PROPERTIES_PREFIX
+ "ProducesChecked";

public void setProducesChecked(boolean checked) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is introducing a ConcurrentHashMap::put there, but TBH it's still better than performing the check twice I think...
2 qq:

  1. ClassRouting vs FixedProduces handler's are always running in that order?
  2. Do we have other mechanism to store this information as a plain field somewhere instead, in the context?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ClassRouting vs FixedProduces handler's are always running in that order?

Yes.

Do we have other mechanism to store this information as a plain field somewhere instead, in the context?

We certainly can, but I was removing fields from the context because it was getting to big and we wanted to make it fit better in cache lines :)

Copy link
Contributor

Choose a reason for hiding this comment

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

I can check with JOL, and if it is within some padding I am +1 to move it to a field, it sadly can matter in bench-marketing :"/ but need to be sure that's free

@quarkus-bot

This comment has been minimized.

@geoand
Copy link
Contributor Author

geoand commented Dec 11, 2023

Waiting for a perf-lab run to see how this change affects performance

@franz1981
Copy link
Contributor

Waiting the perf job to complete

@quarkus-bot

This comment has been minimized.

@franz1981
Copy link
Contributor

ok @geoand it seems that the performance now is right, and the behaviour too, but the ConcurrentHashMap::put in the hot path is just too costy; at the point where the cost is moved a bit toward it, see

image

Check the setProducesChecked method which absorb the most of the cost now
I'm checking with JOL if moving to a field will work for us

@geoand
Copy link
Contributor Author

geoand commented Dec 11, 2023

Ouch...

These checks have potentially already
been performed in ClassRoutingHandler

Closes: quarkusio#37637
@geoand
Copy link
Contributor Author

geoand commented Dec 11, 2023

I converted it to a regular field

@franz1981
Copy link
Contributor

Rerunning the perf ci on this

@geoand
Copy link
Contributor Author

geoand commented Dec 11, 2023

Thanks

@franz1981
Copy link
Contributor

The perf CI is quite happy and we moved from 4 M req/sec to 4.3 M req/sec: now checking with JOL

@geoand
Copy link
Contributor Author

geoand commented Dec 11, 2023

Super!

@franz1981
Copy link
Contributor

franz1981 commented Dec 11, 2023

JDK >= 15, COOPS, CCPS, 16 bytes align

org.jboss.resteasy.reactive.server.core.ResteasyReactiveRequestContext object internals:
OFF  SZ                           TYPE DESCRIPTION                                                VALUE
  0   8                                (object header: mark)                                      N/A
  8   4                                (object header: class)                                     N/A
 12   4                            int AbstractResteasyReactiveContext.position                   N/A
 16   1                        boolean AbstractResteasyReactiveContext.suspended                  N/A
 17   1                        boolean AbstractResteasyReactiveContext.requestScopeActivated      N/A
 18   1                        boolean AbstractResteasyReactiveContext.running                    N/A
 19   1                        boolean AbstractResteasyReactiveContext.abortHandlerChainStarted   N/A
 20   1                        boolean AbstractResteasyReactiveContext.closed                     N/A
 21   3                                (alignment/padding gap)                                    
 24   4                            H[] AbstractResteasyReactiveContext.handlers                   N/A
 28   4                            H[] AbstractResteasyReactiveContext.abortHandlerChain          N/A
 32   4                      Throwable AbstractResteasyReactiveContext.throwable                  N/A
 36   4                       Executor AbstractResteasyReactiveContext.executor                   N/A
 40   4                       Executor AbstractResteasyReactiveContext.lastExecutor               N/A
 44   4            Map<String, Object> AbstractResteasyReactiveContext.properties                 N/A
 48   4              ThreadSetupAction AbstractResteasyReactiveContext.requestContext             N/A
 52   4                    ThreadState AbstractResteasyReactiveContext.currentRequestScope        N/A
 56   4       List<CompletionCallback> AbstractResteasyReactiveContext.completionCallbacks        N/A
 60   4                     Deployment ResteasyReactiveRequestContext.deployment                  N/A
 64   4                       Object[] ResteasyReactiveRequestContext.parameters                  N/A
 68   4                RuntimeResource ResteasyReactiveRequestContext.target                      N/A
 72   4                         Object ResteasyReactiveRequestContext.pathParamValues             N/A
 76   4                        UriInfo ResteasyReactiveRequestContext.uriInfo                     N/A
 80   4                         Object ResteasyReactiveRequestContext.endpointInstance            N/A
 84   4                         Object ResteasyReactiveRequestContext.result                      N/A
 88   4                   LazyResponse ResteasyReactiveRequestContext.response                    N/A
 92   4                HttpHeadersImpl ResteasyReactiveRequestContext.httpHeaders                 N/A
 96   4                         Object ResteasyReactiveRequestContext.requestEntity               N/A
100   4                        Request ResteasyReactiveRequestContext.request                     N/A
104   4                   EntityWriter ResteasyReactiveRequestContext.entityWriter                N/A
108   4    ContainerRequestContextImpl ResteasyReactiveRequestContext.containerRequestContext     N/A
112   4   ContainerResponseContextImpl ResteasyReactiveRequestContext.containerResponseContext    N/A
116   4                         String ResteasyReactiveRequestContext.method                      N/A
120   4                         String ResteasyReactiveRequestContext.originalMethod              N/A
124   4                         String ResteasyReactiveRequestContext.path                        N/A
128   4                         String ResteasyReactiveRequestContext.absoluteUri                 N/A
132   4                         String ResteasyReactiveRequestContext.scheme                      N/A
136   4                         String ResteasyReactiveRequestContext.authority                   N/A
140   4                         String ResteasyReactiveRequestContext.remaining                   N/A
144   4               EncodedMediaType ResteasyReactiveRequestContext.responseContentType         N/A
148   4                   Annotation[] ResteasyReactiveRequestContext.methodAnnotations           N/A
152   4                   Annotation[] ResteasyReactiveRequestContext.additionalAnnotations       N/A
156   4                   Annotation[] ResteasyReactiveRequestContext.allAnnotations              N/A
160   4                           Type ResteasyReactiveRequestContext.genericReturnType           N/A
164   4                    InputStream ResteasyReactiveRequestContext.inputStream                 N/A
168   4                 List<UriMatch> ResteasyReactiveRequestContext.matchedURIs                 N/A
172   4            ReaderInterceptor[] ResteasyReactiveRequestContext.readerInterceptors          N/A
176   4            WriterInterceptor[] ResteasyReactiveRequestContext.writerInterceptors          N/A
180   4                SecurityContext ResteasyReactiveRequestContext.securityContext             N/A
184   4                   OutputStream ResteasyReactiveRequestContext.outputStream                N/A
188   4                   OutputStream ResteasyReactiveRequestContext.underlyingOutputStream      N/A
192   4                       FormData ResteasyReactiveRequestContext.formData                    N/A
196  12                                (object alignment gap)                                     
Instance size: 208 bytes
Space losses: 3 bytes internal + 12 bytes external = 15 bytes total

Right now we have room for 15 bytes to fill, so we should be fine.
We can than decide, if we have too many boolean ones to replace it with a single BitSet-like structure using a single byte able to cover for

 16   1                        boolean AbstractResteasyReactiveContext.suspended                  N/A
 17   1                        boolean AbstractResteasyReactiveContext.requestScopeActivated      N/A
 18   1                        boolean AbstractResteasyReactiveContext.running                    N/A
 19   1                        boolean AbstractResteasyReactiveContext.abortHandlerChainStarted   N/A
 20   1                        boolean AbstractResteasyReactiveContext.closed                     N/A
 21   3                                (alignment/padding gap)                                    

and the new one you're adding. Let me know and I can send a futrher pr later for it.

@geoand
Copy link
Contributor Author

geoand commented Dec 11, 2023

Sure yeah, we can do that (I don't remember how many booleans we have, but it should be a few)

Copy link
Contributor

@franz1981 franz1981 left a comment

Choose a reason for hiding this comment

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

LGTM!

@quarkus-bot
Copy link

quarkus-bot bot commented Dec 11, 2023

✔️ The latest workflow run for the pull request has completed successfully.

It should be safe to merge provided you have a look at the other checks in the summary.

@geoand geoand merged commit 9d9cb79 into quarkusio:main Dec 11, 2023
42 checks passed
@quarkus-bot quarkus-bot bot added the kind/enhancement New feature or request label Dec 11, 2023
@quarkus-bot quarkus-bot bot added this to the 3.7 - main milestone Dec 11, 2023
@geoand geoand deleted the #37637 branch December 12, 2023 06:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Skip performing content negotiation twice
3 participants