Add support for high frequency live observations #2
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Background
I want to use t-digests with grpc services. In a service rpc handler,
you typically encounter each measured event once per invocation.
Using the TDigest that is in
lib
for this is very costly unlessupdates to the digest are amortized. Doing this manually for each
digest is onerous and error-prone; and it seems like a fairly common
need (in my experience).
The idea
Goals:
TDigest seems fine - its mutation functions are a little more "functional"
and return a copy. That's nice, but can be expensive when you're using it
as a tool to control memory cost in a server!
So let's add a wrapper around it: Support retrieving a TDigest at any time,
but make it convenient to record a number with optimally low overhead.
Storing the amortized records in an array lowers the allocation burden versus
a vector, and lets us bypass clear() to reuse. It costs bookkeeping for 1 index
but promises to give the most benefit possible from an object_pool::Pool and it
lowers the cost of the periodic flush to the backing tdigest (though only a small
amount).
Testing
Updating a TDigest for each invocation of a service api costs around
840ns according to some simple Criterion benchmarking:
Results
for plain usage like:
You get performance that beats the goal at nearly 1/20 the latency of
the naive unary tdigest update:
If you have
mut
you can further improve to better than 1/25 the naivestrategy for unary tdigest updates: