-
Notifications
You must be signed in to change notification settings - Fork 9.8k
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
raft: disable XXX_NoUnkeyedLiteral, XXX_unrecognized, and XXX_sizecache fields in protos #12790
Conversation
@tbg mind taking a look at this when you get a chance? I'm not able to assign a reviewer to this. |
1c7e664
to
5f9aaf7
Compare
This test checks the in-memory size of each proto struct to detect unexpected changes to their memory representation.
…he fields in protos This commit removes the `XXX_NoUnkeyedLiteral`, `XXX_unrecognized`, and `XXX_sizecache` auto-generated fields from generated protobuf structs in the raft package. This was done for all of the same reasons CockroachDB removed the generation of these fields in cockroachdb/cockroach#38404. They come with very limited advantages but moderate disadvantages. `XXX_NoUnkeyedLiteral` and `XXX_sizecache` were only enabled recently in cc7b4fa, and this appears to have been unintentional. Meanwhile, `XXX_unrecognized` has been around for longer and has arguably more reason to stay because it can assist with forwards compatibility. However, any real mixed-version upgrade story for this package is mostly untold at this point, and keeping this field seems just as likely to cause unexpected bugs (e.g. a field was propagated but not updated correctly when passed through an old version) as it seems to fix real issues, so it also doesn't warrant its cost. This reduces the in-memory representation size of all Raft protos. Notably, it reduces the memory size of an `Entry` proto from *80 bytes* to *48 bytes* and the memory size of a `Message` proto from *392 bytes* to *264 bytes*. Both of these structs are used frequently, and often in slices, where this wasted space really starts to add up. This was motivated by a regression in microbenchmarks in CockroachDB due to cc7b4fa, which was caught in cockroachdb/cockroach#62212.
5f9aaf7
to
e51c697
Compare
Codecov Report
@@ Coverage Diff @@
## master #12790 +/- ##
==========================================
- Coverage 52.83% 48.25% -4.58%
==========================================
Files 383 383
Lines 31347 31346 -1
==========================================
- Hits 16561 15127 -1434
- Misses 12771 14297 +1526
+ Partials 2015 1922 -93
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
Really nice regressions finding infrastucture.
@dsnet: Joe, could you, please, asses risk-factor of using this flags for potential gogo -> golang/protobuf generator migration
|
Has no effect on the runtime, but I don't recommend setting it. There is no memory benefit to removing this field, and causes compatibility issues at scale when users declare unkeyed struct literals of your messages and you unexpectedly break them when you add a new message field.
As you may be aware, the runtime handles this gracefully. Calling
If the type has a generated |
Thank you two for taking a look, especially over the weekend!
You raise a good point. It got picked up as a regression in our test suite because But the testing added in this PR demonstrates that some messages were hit even worse. Those that contained nested messages grew even more. For instance,
Right, this is true if the field is not at the end of generated protos. But if it is the last field in the generated proto, the empty struct does increase the size of the parent struct due to golang/go#9401. I sympathize with everything you say here and generally like the idea of the field, but if it has a runtime cost as it would here, was only recently introduced a few months ago, and can be replaced by the use of
This is what we found in cockroachdb/cockroach@1967c25 as well. With gogo/protobuf's generated |
Thank you, Joe & Nathan,
To be honest, I don't understand why Raft is processing everywhere slices of Entry(s) & Message(s) instead of pointers to them. I would assume there must be a lot of copying going on that could be avoided. Is the 'cache' efficiency reason here ? |
This commit picks up etcd-io/etcd#12790, which resolves a regression observed in cockroachdb#62212. Picks up the following four commits: - etcd-io/etcd@87258ef - etcd-io/etcd@2c2456b - etcd-io/etcd@ebc0174 - etcd-io/etcd@e51c697 ``` name old time/op new time/op delta EntryCache-16 114µs ± 7% 96µs ±12% -15.29% (p=0.000 n=19+19) EntryCacheClearTo-16 37.7µs ± 4% 34.9µs ± 4% -7.55% (p=0.000 n=17+18) name old alloc/op new alloc/op delta EntryCacheClearTo-16 1.28kB ± 0% 0.77kB ± 0% -40.00% (p=0.000 n=20+20) EntryCache-16 83.3kB ± 0% 50.0kB ± 0% -39.95% (p=0.000 n=19+20) name old allocs/op new allocs/op delta EntryCache-16 3.00 ± 0% 3.00 ± 0% ~ (all equal) EntryCacheClearTo-16 1.00 ± 0% 1.00 ± 0% ~ (all equal) ```
62819: go.mod: bump etcd/raft to pick up proto size improvements r=tbg a=nvanbenschoten This commit picks up etcd-io/etcd#12790, which resolves a regression observed in #62212. Picks up the following four commits, each of which I've reviewed for safety: - etcd-io/etcd@87258ef - etcd-io/etcd@2c2456b - etcd-io/etcd@ebc0174 - etcd-io/etcd@e51c697 ``` name old time/op new time/op delta EntryCache-16 114µs ± 7% 96µs ±12% -15.29% (p=0.000 n=19+19) EntryCacheClearTo-16 37.7µs ± 4% 34.9µs ± 4% -7.55% (p=0.000 n=17+18) name old alloc/op new alloc/op delta EntryCacheClearTo-16 1.28kB ± 0% 0.77kB ± 0% -40.00% (p=0.000 n=20+20) EntryCache-16 83.3kB ± 0% 50.0kB ± 0% -39.95% (p=0.000 n=19+20) name old allocs/op new allocs/op delta EntryCache-16 3.00 ± 0% 3.00 ± 0% ~ (all equal) EntryCacheClearTo-16 1.00 ± 0% 1.00 ± 0% ~ (all equal) ``` Co-authored-by: Nathan VanBenschoten <nvanbenschoten@gmail.com>
This commit picks up etcd-io/etcd#12790, which resolves a regression observed in cockroachdb#62212. Picks up the following four commits: - etcd-io/etcd@87258ef - etcd-io/etcd@2c2456b - etcd-io/etcd@ebc0174 - etcd-io/etcd@e51c697 ``` name old time/op new time/op delta EntryCache-16 114µs ± 7% 96µs ±12% -15.29% (p=0.000 n=19+19) EntryCacheClearTo-16 37.7µs ± 4% 34.9µs ± 4% -7.55% (p=0.000 n=17+18) name old alloc/op new alloc/op delta EntryCacheClearTo-16 1.28kB ± 0% 0.77kB ± 0% -40.00% (p=0.000 n=20+20) EntryCache-16 83.3kB ± 0% 50.0kB ± 0% -39.95% (p=0.000 n=19+20) name old allocs/op new allocs/op delta EntryCache-16 3.00 ± 0% 3.00 ± 0% ~ (all equal) EntryCacheClearTo-16 1.00 ± 0% 1.00 ± 0% ~ (all equal) ```
This commit removes the
XXX_NoUnkeyedLiteral
,XXX_unrecognized
, andXXX_sizecache
auto-generated fields from generated protobuf structs in the raft package. This was done for all of the same reasons CockroachDB removed the generation of these fields in cockroachdb/cockroach#38404. They come with very limited advantages but moderate disadvantages.XXX_NoUnkeyedLiteral
andXXX_sizecache
were only enabled recently in cc7b4fa, and this appears to have been unintentional. Meanwhile,XXX_unrecognized
has been around for longer and has arguably more reason to stay because it can assist with forwards compatibility. However, any real mixed-version upgrade story for this package is mostly untold at this point, and keeping this field seems just as likely to cause unexpected bugs (e.g. a field was propagated but not updated correctly when passed through an old version) as it seems to fix real issues, so it also doesn't warrant its cost.This reduces the in-memory representation size of all Raft protos. Notably, it reduces the memory size of an
Entry
proto from 80 bytes to 48 bytes and the memory size of aMessage
proto from 392 bytes to 264 bytes. Both of these structs are used frequently, and often in slices, where this wasted space really starts to add up.This was motivated by a regression in microbenchmarks in CockroachDB due to cc7b4fa, which was caught in cockroachdb/cockroach#62212.