-
Notifications
You must be signed in to change notification settings - Fork 2.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
Do not generate XXX fields in protobufs #1725
Do not generate XXX fields in protobufs #1725
Conversation
We don't need them. By gettig rid of them we achieve: - smaller memory footprint - smaller payloads on the wire - same in-memory layout with core Prometheus structs opening path for all sorts of optimisations such as unsafe casts, leading to better memory use and faster :) - see related issue: prometheus/prometheus#6029 The tests show SG memory allocations dropped 5% for query execution: - Showing nodes accounting for -359.20MB, 6.19% of 5798.93MB total Signed-off-by: Philip Panyukov <[email protected]>
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.
That is amazing! I think that opens many doors for improvements!
Will review later as we prepare for PromCon.
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.
Could this possibly hinder the upgrade paths in the future for our users if these types will ever be extended? I guess @bwplotka could chime in here about the actual stability of these things (:
We already extended this not such a long time ago:
#1284
#750
But I guess this trade-off could be acceptable given that we reduce the memory usage by ~5%.
So, after a bit of digging on these XXX fields, it's a touchy subject apparently. They came and gone and came back again. Apparently there was a lot of upset when these fields disappeared on one release of proto3 after Google decided they don't need them internally and therefore let's ditch them for everyone. So they made it back. To give some idea what they are and what they are used for: https://github.com/golang/protobuf/blob/master/README.md
https://groups.google.com/forum/#!msg/golang-nuts/F5xFHTfwRnY/sPv5nTVXBQAJ
I think we can certainly ditch The Any thoughts from anyone? |
Also, this produces same result as using |
Yes. It seems to help in parsing latency. I think we can use tradeoff of parsing latency vs the memory used |
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! Just small comment to fill.
pkg/store/storepb/rpc.proto
Outdated
@@ -11,6 +11,11 @@ option (gogoproto.marshaler_all) = true; | |||
option (gogoproto.unmarshaler_all) = true; | |||
option (gogoproto.goproto_getters_all) = false; | |||
|
|||
// Do not generate XXX fields. As per https://stackoverflow.com/a/58088012 |
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.
Let's comment why (:
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.
Done?
// Do not generate XXX fields to reduce memory footprint and opening a door
// for zero-copy casts to/from prometheus data types.
Signed-off-by: Philip Panyukov <[email protected]>
More detailed and precise measurements of the effect of this change. Memory profile deltas for start/end of each of these functions: Querier, BEFORE:
AFTER:
RESULT: 36% reduction for StoreGateway, BEFORE:
AFTER:
RESULT: 22% reduction for |
* Do not generate XXX fields in protobufs We don't need them. By gettig rid of them we achieve: - smaller memory footprint - smaller payloads on the wire - same in-memory layout with core Prometheus structs opening path for all sorts of optimisations such as unsafe casts, leading to better memory use and faster :) - see related issue: prometheus/prometheus#6029 The tests show SG memory allocations dropped 5% for query execution: - Showing nodes accounting for -359.20MB, 6.19% of 5798.93MB total Signed-off-by: Philip Panyukov <[email protected]> * comment to explain why do don't generate XXX fields in protobufs Signed-off-by: Philip Panyukov <[email protected]> Signed-off-by: suntianyuan <[email protected]>
* Do not generate XXX fields in protobufs We don't need them. By gettig rid of them we achieve: - smaller memory footprint - smaller payloads on the wire - same in-memory layout with core Prometheus structs opening path for all sorts of optimisations such as unsafe casts, leading to better memory use and faster :) - see related issue: prometheus/prometheus#6029 The tests show SG memory allocations dropped 5% for query execution: - Showing nodes accounting for -359.20MB, 6.19% of 5798.93MB total Signed-off-by: Philip Panyukov <[email protected]> * comment to explain why do don't generate XXX fields in protobufs Signed-off-by: Philip Panyukov <[email protected]> Signed-off-by: Aleksey Sin <[email protected]>
Changes
Use options in
.proto
files to not generate XXX fields in Go structs.We don't need XXX fields - the interface is so stable it is VERY unlikely we'd ever need these at all, ever. By getting rid of them we achieve:
smaller payloads on the wire(edit: XXX are not put on the wire it seems)Why this matters from memory perspective:
storepb.Label
type (with XXX fields): 64 bytesstorepb.Label
type (without XXX): 32 bytesstorepb.Label
this mattersWhy this matters to have same in-memory layout with core Prometheus structs:
storepb
types because of these XXX fieldsThe tests show Store Gateway memory allocations dropped 5% for query execution:
From code perspective, this is example of how much less memory is used for one query in
blockSeries
func:Verification
Verification
realistic-k8s-1w-small
profilecount({__name__=~".+"}) by (__name__)
BucketStore.Series
to dump heap profile at the start and end of the function call.PNG attached
Heap profiles attached
heap-series-1-after-base.pb.gz
heap-series-1-after-change.pb.gz
EDIT 1: Notes and test on compatibility
I've done some tests on the compatibility to make sure this is not a breaking change for anything:
Everything seems to work just fine between the two.
Which of course makes sense since I also discovered that XXX fields are not put on the wire :)
smaller payloads on the wire(edit: XXX are not put on the wire it seems)Basically this means that individual components can use or not use XXX fields and the comms between them are still OK.
Hopefully this should give people more confidence that this PR can be merged without ill effects.