-
-
Notifications
You must be signed in to change notification settings - Fork 250
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
Optimize metrics wrapper #1850
Optimize metrics wrapper #1850
Conversation
(for { | ||
_ <- failures.get.flatMap(metrics.recordFailures) | ||
timings <- timings.get | ||
nodeOffsets = resolveNodeOffsets(timings) | ||
_ <- metrics.recordSuccesses(nodeOffsets, timings) | ||
} yield ()).forkDaemon |
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 not sure how I feel about forking this effect, but it's by far the most performant implementation. With forking, it becomes faster than the ApolloTracing
wrapper (see performance result in PR description)
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.
Makes sense to not make the execution slower because we're updating the metrics. And since this wrapper does't wrap pure fields, we don't create too many useless fibers.
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.
By the way we're forking only once per query execution here, so the effect of the forking itself should be extremely minimal. My only concern is that in the very unlikely case that the calculation of offsets + writing of metrics is slower than the query execution, this could lead to a memory leak.
However, the chances of that happening are extremely low since in almost all cases the query execution will be slower than this
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 actually think being able to separate the measurements from the final calculation/reporting of metrics is the most beautiful and clever part of this change, so I definitely think we should keep the forkDaemon
. :)
Also, a single forkDaemon
call is likely to pale in comparison to all other fork
calls during query execution.
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.
Beautiful optimization (once I managed to figure out how it works :)).
The only thing that caught me is if the .view
here actually does anything, since we're directly materializing it to a vector?
@frekw it's a space-complexity optimization rather than a time-complexity one. Without |
@ghostdogpr are you okay with merging this one in? |
Fairly certain we can optimise it further, but at least now it's not cripplingly slow. Open to suggestions on what else can be improved. The metrics wrapper is now ~x50 faster but still twice as slow as the
ApolloTracing
wrapper.Before:
After
If we fork the writing of metrics, then the
metricsBenchmark
becomes faster than theApolloTracing
wrapper: