-
Notifications
You must be signed in to change notification settings - Fork 9.9k
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: make Message.Snapshot nullable, halve struct size #14592
Conversation
8a6a77a
to
2c00b9b
Compare
Codecov Report
@@ Coverage Diff @@
## main #14592 +/- ##
==========================================
+ Coverage 75.48% 75.52% +0.03%
==========================================
Files 457 457
Lines 37314 37317 +3
==========================================
+ Hits 28166 28182 +16
+ Misses 7369 7361 -8
+ Partials 1779 1774 -5
Flags with carried forward coverage won't be shown. Click here to find out more.
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
If the message is rarely used why change it at all. I know 52% improvement seems great, however if we say rare means ~1/1000 proto messages are snapshot, then this i only 0.05% improvement. This would not be as bad of an improvement if it didn't introduce breaking change concerns. Now we need to spend time to add a specific e2e tests just to ensure this doesn't break. I would say that work we will need to put is greater than improvements. Are there no lower hanging fruits than this? |
No, not yet. We should perform such verification. Are there cross-version tests in etcd? @serathius mentioned e2e testing, which may include mixed version testing. If no such testing exists, we can piggyback on top of CockroachDB's mixed-version testing to gain more confidence in this change.
Also not yet. Are there any such benchmarks in etcd which exercise raft that you'd like to see? If not, I can evaluate this change using the raft benchmarking harness (rafttoy) that we developed to measure the performance impact of variations in the use of
This commit makes the snapshot header in the message struct nullable, so that non-snapshot messages (the ~999/1000 messages that aren't snapshots) don't need to pay the cost of this large snapshot header either in-memory or over the wire. That reduces the size of the memory representation of a |
We do have cluster downgrade test, but we don't have mixed version testing, such as 3.5 mixes with 3.6 version. We need to make sure etcd cluster with mixed version can handle raft message correctly. So please add at least one e2e test for this. Currently we only have benchmark tool (FYI. #14394 (comment)). I think we also need to verify the memory & network bandwidth usage probably by the metrics. Does it also make sense to add golang benchmark test ? |
Thanks for the pointers @ahrtr. I ran some system and micro-benchmarks. All performance testing was run on a Results on one-server cluster
Results on
Results on branch
Results on three-server cluster
Results on
Results on branch
These tests show stable results and very little difference across branches. Maybe a 0.1% increase in throughput, but I did not run enough iterations to determine whether that difference is in the noise. That's mostly expected, given the size of the benchmark, its interaction with disk and network IO, and how targeted this change is. Results on microbenchmarksMicrobenchmarks show a statistically significant and sizable improvement in proposal latency and memory allocations (count and size).
|
Thanks @nvanbenschoten for the feedback, which looks good. Usually messages do not include snapshot, so it doesn't make sense to always get the snapshot header included in each message. This PR overall looks good to me. cc @ptabor and @tbg to double check. We also need to add an mixed version testing (the main/3.6 mix with the previous version/3.5). Please let me know if you need help on this. |
I had idea how to incorporate mixed version testing into common tests by just adding new test scenarios. |
I would appreciate some help with this, as I'm not up to speed on the state of mixed-version testing in etcd and it also sounds like this is in flux. At a high level, I think a test that 1) sends a Raft snapshot from |
Sure. Let me and @serathius to take care of the e2e test. |
@ahrtr did you also want to review? Going to assign you just in case. |
We are still in progress of adding the mix-versions test. We already added some such tests in #14697, but I am planing to add more cases to cover the snapshot scenario as pointed out in #14592 (comment). When I finish the snapshot cases, then I would request to rebase this PR. If all workflows are green, then I am OK to merge this PR. |
2c00b9b
to
a0b8df4
Compare
This commit makes the rarely used `raftpb.Message.Snapshot` field nullable. In doing so, it reduces the memory size of a `raftpb.Message` message from 264 bytes to 128 bytes — a 52% reduction in size. While this commit does not change the protobuf encoding, it does change how that encoding is used. `(gogoproto.nullable) = false` instruct the generated proto marshaling logic to always encode a value for the field, even if that value is empty. `(gogoproto.nullable) = true` instructs the generated proto marshaling logic to omit an encoded value for the field if the field is nil. This raises compatibility concerns in both directions. Messages encoded by new binary versions without a `Snapshot` field will be decoded as an empty field by old binary versions. In other words, old binary versions can't tell the difference. However, messages encoded by old binary versions with an empty Snapshot field will be decoded as a non-nil, empty field by new binary versions. As a result, new binary versions need to be prepared to handle such messages. While Message.Snapshot is not intentionally part of the external interface of this library, it was possible for users of the library to access it and manipulate it. As such, this change may be considered a breaking change. Signed-off-by: Nathan VanBenschoten <nvanbenschoten@gmail.com>
a0b8df4
to
0f9d7a4
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
Thank you @nvanbenschoten
I will add additional mix version test (FYI. #14707 (comment)), but this PR should be good to go.
This commit makes the rarely used
raftpb.Message.Snapshot
field nullable. In doing so, it reduces the memory size of araftpb.Message
message from 264 bytes to 128 bytes — a 52% reduction in size.While this commit does not change the protobuf encoding, it does change how that encoding is used.
(gogoproto.nullable) = false
instruct the generated proto marshaling logic to always encode a value for the field, even if that value is empty.(gogoproto.nullable) = true
instructs the generated proto marshaling logic to omit an encoded value for the field if the field is nil.This raises compatibility concerns in both directions. Messages encoded by new binary versions without a
Snapshot
field will be decoded as an empty field by old binary versions. In other words, old binary versions can't tell the difference. However, messages encoded by old binary versions with an empty Snapshot field will be decoded as a non-nil, empty field by new binary versions. As a result, new binary versions need to be prepared to handle such messages.While Message.Snapshot is not intentionally part of the external interface of this library, it was possible for users of the library to access it and manipulate it. As such, this change may be considered a breaking change.
Please read https://github.com/etcd-io/etcd/blob/main/CONTRIBUTING.md#contribution-flow.