-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
cloudv2: Higher resolution for Histograms #3302
Conversation
Codecov Report
@@ Coverage Diff @@
## master #3302 +/- ##
==========================================
- Coverage 73.21% 73.19% -0.02%
==========================================
Files 258 258
Lines 19886 19895 +9
==========================================
+ Hits 14559 14563 +4
- Misses 4404 4408 +4
- Partials 923 924 +1
Flags with carried forward coverage won't be shown. Click here to find out more.
|
0a58f7c
to
0a0c400
Compare
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.
LGTM in general 👍
I left some not blocking comments.
But I would prefer if we get some tests with values between 0 and 1 which is what this was about. Maybe even with some values that the browser team think are representable.
@@ -151,6 +164,9 @@ func histogramAsProto(h *histogram, time int64) *pbcloud.TrendHdrValue { | |||
if h.ExtraHighBucket > 0 { | |||
hval.ExtraHighValuesCounter = &h.ExtraHighBucket | |||
} | |||
// We don't expect to change the minimum resolution at runtime | |||
// so a pointer is safe here | |||
hval.MinResolution = &h.MinimumResolution |
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.
Is there are reason to use a pointer though?
It won't save memory and will add dereferencing the point when we have to actually write it.
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 guess the problem is that this is because in the protobuf definition this is not required 🤦
Not certain we can do anythign about 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.
Yeah, the reason is how Protobuf defines optional values. We haven't released yet the new cloud output v2 as the default so we could think of migrating directly to a new Protobuf version making it required. But my feeling is that it would require a maintenance window.
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 believe that if we un-optional this field, this doesn't really change anything for the backend?
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.
@esquonk if the suggestion is to change it only on the client then it would require having different proto file versions between the backend and client, that doesn't sound optimal to me.
Instead, if you mean for both of them, then In that case, the problem is how to handle the versioning. If we set the field on the backend as required then the already k6 v0.46.0 released version will stop working if we force the K6_CLOUD_API_VERSION=2
overwriting it from the backend. We could consider it as a no-problem as we are pretty confident that we will set it directly from the code releasing v0.47.0, but I'm not sure. Thoughts?
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.
LGTM, but joining to Mihail on his comments 👍
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.
LGTM!
Do we have any statistics on how much this change makes changes over 1 less accurate?
I guess it will be fairly good to have some kind of graph showing how accurate the samples are between the values 0 and ... something Less say whatever 1 minute is in ms so 1 *60 * 100 = 6000?
That graph is mostly interesting for the release notes, but it will still be good to have it ealier IMO. |
We should not lose any precision because what we are doing is just using a factor for moving the values across the histogram. The relative error rate is generated from the number of buckets that we have in the range, and it is a constant value. In our case the error rate is ~1%.
So the boundaries of each value are just upscaled for storage and downscaled for query but they will be the same.
@mstoykov does it make sense for you? |
@codebien it makes some sense ... but we still change the number of buckets. From my experiments it is barely noticeable in the values we have. func TestSequence(t *testing.T) {
resolution := float64(0.001)
first := float64(50_000)
last := resolveBucketIndex(float64(first) / resolution)
first_last := last
max := float64(60_000)
increment := float64(1)
for i := first; i <= max; i += increment {
index := resolveBucketIndex(float64(i) / resolution)
if last != index {
// fmt.Println(last, index, i)
last = index
}
}
fmt.Printf("buckets total in range %f to %f with resolution %f are %d\n", first, max, resolution, last-first_last)
} For example will result in
vs
So 1 bucket more - so very small reduction of accuracy in the 50 to 60 seconds. If I go in bigger ranges the difference is once again 1-2 either way, so it seems okay. Obviously if you go from 0 to 1 the difference is huge :
vs
I think we can tl;dr it to "there is no lost of resolution in the values above 1" while there is significant improvement in the ones between 0 and 1 edit: p.s. the code was added to |
a7dec90
to
a6f757d
Compare
Hey @olegbespalov @mstoykov I've pushed a new fixup for fixing #3302 (comment). It was a mistake because we are checking the max value after that the resolution is applied, so the value will be checked already as the final value. Can you take another look, please? |
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.
Generally LGTM 👍
But I prefer to do a clean-up of the tests (mentioned in the comments) in the current PR to avoid future confusion.
However, I don't know how urgent is merging this, so approving it.
h := newHistogram() | ||
// TODO: refactor | ||
// An hack for preserving as the default for the tests the old value 1.0 |
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.
TBH, it seems right now is the best moment to refactor this place to avoid future confusion.
for _, v := range tc.vals { | ||
h.Add(v) | ||
} | ||
tc.exp.MinimumResolution = 1.0 |
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.
nit: it's better to keep this along with the other expectations
@@ -161,57 +180,84 @@ func TestHistogramAddWithMultipleOccurances(t *testing.T) { | |||
Sum: 466.20000000000005, | |||
Count: 5, | |||
} | |||
exp.MinimumResolution = 1.0 |
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.
why not define it in the struct?
Count: 3, | ||
MinimumResolution: 1.0, | ||
} | ||
h.MinimumResolution = 1.0 |
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.
Isn't it already done on the line 210? (straight after h := newHistogram()
) 🤔
Hey @olegbespalov, we decided to make the I will reference the comments here directly in the new PR. |
@codebien Sure, go ahead and merge it 👍 |
We increased the resolution for the histogram using a different min_resolution value. It increases the range of supported values. Now, it supports decimal values between 0 and 1. min_resolution is a factor that scales the ingested value, in this way, with the set value of 0.001, it supports 3 decimal digits where before there was only the option for aggregating integer values.
What?
It expands the resolution for Histograms, setting
0.001
as the minimum resolution.Why?
It allows us to support decimal numbers up to 3 digits, increasing the detail of the values that we can store.