-
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
Replace Ordered
with an iterator in export.Labels
.
#567
Conversation
afdec3c
to
5b727fc
Compare
I apologize in advance, but there are some things I don't like about this approach. Sorry! The use of an iterator pattern feels not like Go to me, and it requires some additional allocations that don't feel necessary. When the SDK creates its We have a Of the three fields in
The Sorry to ask for another approach--I'm open to debate on this topic. Maybe I've got it wrong. As for the next part of #539, I was imagining new fields added to the |
No worries.
I got the inspiration for the iterator pattern from reflect.MapIter and bufio.Scanner. I guess this is as Go-like as doing
Alright, I have kept the iterator, but I made it a simple struct, so creating it shouldn't result in any allocation. This resulted in dropping the zero iterator and reflect iterator thingies. So that's good. I added the
I think I'd like to do it in the next PR to avoid making this bigger. But one thing about the Also (for the future PR), I can't yet see how to move contents of
We seem to lose the ability of using
It's all good - it actually led me to a simpler design I think. Thanks for that. I have pushed my changes so far. One thing - I called my interface
Yeah, something to experiment with when this PR lands. |
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.
This is great!
Updated. |
This is really an inconvenient implementation detail leak - we may want to store labels in a different way. Replace it with an iterator - it does not force us to use slice of key values as a storage in the long run.
It may come in handy in several situations, where we don't have access to export.Labels object, but only to the label iterator.
Makes my life easier when writing a benchmark. Might also be an alternative to cloning the iterator.
By not using the value created by `reflect.New()`, but rather by `reflect.ValueOf()`, we get a non-addressable array in the value, which does not infer an allocation cost when getting an element from the array.
This can be substituted by a reflect value iterator that goes over a value with a zero-sized array.
In the long run this will completely replace the LabelIterator interface.
It's a leftover from interface times and now it's pointless - the iterator is a simple struct, so cloning it is a simple copy.
The sole existence of Reset was actually for benchmarking convenience. Now we can just copy the iterator cheaply, so a need for Reset is no more.
So we won't get into problems when several goroutines want to iterate the same labels at the same time. Not sure if this would be a big deal, since every goroutine would compute the same reflect.Value, but concurrent write to the same memory is bad anyway. And it doesn't cost us any extra allocations anyway.
35ac826
to
da0ee3c
Compare
Rebased, resolved the conflicts. |
This is to address the first step in #539. The
metric.SDK.Labels()
used to store the slice passed to it, so the slice could still be modified after the function returned. Now it still modifies the passed slice in place, but it isn't used after the function is finished. Theexport.Labels
does not expose the labels slice anymore. Instead it has a getter for an iterator, so we are not forced to use a slice, but have some other possibilities of storing the labels.Currently, for empty labelset, we use a "zero" iterator, for labelsets with less than 11 keys, we use the reflect-based iterator, for larger labelsets we do a one-time allocation at the checkpoint time and use a slice iterator.
Benchmarks before:
Benchmarks after:
Iterator benchmarks: