-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Some CPU overhead from ChainedInstrumentation #3436
Comments
We use this workaround /**
* ChainedInstrumentation is slow, so we use this class to more manually combine multiple instrumentations into one.
*/
class FastGraphQLInstrumentations(
private val searchQueryCacheTTLInstrumentation: SearchQueryCacheTTLInstrumentation,
private val disableCacheInstrumentation: DisableCacheInstrumentation,
private val modifyHttpStatusCodeInstrumentation: ModifyHttpStatusCodeInstrumentation
) : SimplePerformantInstrumentation() {
override fun instrumentExecutionResult(
executionResult: ExecutionResult?,
parameters: InstrumentationExecutionParameters?,
state: InstrumentationState?
): CompletableFuture<ExecutionResult> {
val queryContext = parameters?.graphQLContext?.get<QueryContext>("queryContext")
if (queryContext != null && executionResult != null) {
val result = modifyHttpStatusCodeInstrumentation.modifyHttpStatusCode(queryContext, executionResult)
if (result != null) {
return result
}
}
if (queryContext != null && executionResult != null) {
val result = searchQueryCacheTTLInstrumentation.addCacheTTLForShortSearchQueries(queryContext, executionResult)
if (result != null) {
return result
}
}
if (queryContext != null && executionResult != null) {
val result = disableCacheInstrumentation.disableCaching(queryContext, executionResult)
if (result != null) {
return result
}
}
return super.instrumentExecutionResult(executionResult, parameters, state)
}
} |
So in many ways this is expected. The profiling above shows
which is a hashmap of states in the chain. A map look up should not be slow but it is being called often. The same is true of beginField - if you query has lots of fields - the instrumentation is going to get a callback for each field. You mention that you have a couple of instrumentations - what are they ? Ideally they would directive from The optimization that @rrva has will be faster because its very specific. The graphql java code needs to be able to generically run any instrumentation. Where as @rrva runs specific bits of code that he is aware of - which is a faster way to run things but its not generic - its highly coupled to specific code That said the next version of graphql-java is trying to reduce the default data loader instrumentation that always gets added. Instead if will be implemented in the engine itself. This MAY save some time but we havent yet done the perf tests for that. |
We have 6 instrumentations, more if a service adds application specific ones - so at least 6 I've fixed this here: |
Signed-off-by: Danny Thomas <dannyt@netflix.com>
Signed-off-by: Danny Thomas <dannyt@netflix.com>
* master: fixed async benchmark - it was non sensical before fix up loading resources from inside jar clean up cleaning up the jhm benchmarks Added Async benchmark for future changes Update README.md Use String concatenation instead of StringBuilder Small code tweaks on recent PR Add instrumentation with null state Add benchmark Avoid Map for instrumentation state. Fixes graphql-java#3436
Closing as fixed in v22 |
Describe the bug
We register more than one instrumentation as part of our DGS framework, which leads to
ChainedInstrumentation
being used. This class shows as a hotspot for field instrumentation in particular. In the case of the application I was looking at, I'd estimate it's 5-8% of the CPU overhead while satisfying queries:Data fetching for this service is all GRPC/Netty/EVCache, so
graphql-java
hotspots become more visible that they might otherwise be; this is very likely the worst case for this class.To Reproduce
Note the overhead of field instrumentation when using chained instrumentations, due to the frequency of
beginField
calls for any non-trivial query.The text was updated successfully, but these errors were encountered: