-
Notifications
You must be signed in to change notification settings - Fork 3.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
roachpb: stop mutating RangeDescriptor when Replicas is called #39489
Conversation
Thoughts? We could go even further with the fastpath and return a slice of the wrapped replicas whenever the voters or learners are all consecutive (and then make this more likely by sorting at the end of both AddReplica and RemoveReplica). |
If we're removing the sort, we can also remove this hacky fix: cockroach/pkg/storage/replica_command.go Lines 1512 to 1527 in b320ff5
|
pkg/roachpb/data_test.go
Outdated
@@ -1587,6 +1587,6 @@ func TestChangeReplicasTrigger_String(t *testing.T) { | |||
}, | |||
} | |||
act := crt.String() | |||
exp := `ADD_REPLICA((n1,s2):3LEARNER): updated=(n4,s5):6,(n1,s2):3LEARNER,(n7,s8):9LEARNER next=10` | |||
exp := `ADD_REPLICA((n1,s2):3LEARNER): updated=(n1,s2):3LEARNER,(n4,s5):6,(n7,s8):9LEARNER next=10` |
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 is this changing? Note that in #39484 I ran into problems because the sorting isn't stable but we're passing ReplicaID zero everywhere, just absorb that PR perhaps?
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.
Oh wait the sorting is going away, nvm
sort.Sort((*byTypeThenReplicaID)(replicas)) | ||
return ReplicaDescriptors{wrapped: *replicas} | ||
func MakeReplicaDescriptors(replicas []ReplicaDescriptor) ReplicaDescriptors { | ||
return ReplicaDescriptors{wrapped: replicas} |
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.
Can't this just be the same underlying type now?
type ReplicaDescriptors []ReplicaDescriptor
I like this, good call. I thought about doing the same but didn't have the fast path on the radar. In a world in which we have "permanent" learners we're going to have to fiddle with this once more, but let's buy into complexity when we truly need this LGTM |
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.
Reviewed 12 of 12 files at r1.
Reviewable status: complete! 1 of 0 LGTMs obtained (waiting on @danhhz)
pkg/roachpb/metadata_replicas.go, line 170 at r1 (raw file):
// For some related mega-comments, see Replica.sendSnapshot. func (d ReplicaDescriptors) Learners() []ReplicaDescriptor { learners := make([]ReplicaDescriptor, 0, len(d.wrapped))
Should we add a fast-path here as well? Most of the time we expect no LEARNERS, right? I guess that would be equivalent to not pre-allocating this slice:
var learners []ReplicaDesciptor
You might be worried about the potential for repeat allocations if we do that, in which case I'd still make the allocation lazy:
var learners []ReplicaDesciptor
for i := range d.wrapped {
if d.wrapped[i].GetType() == ReplicaType_LEARNER {
if learners == nil {
learners = make([]ReplicaDescriptor, 0, len(d.wrapped)-i)
...
d9577fe
to
2d5d653
Compare
It was previously sorting the InternalReplicas field so we could serve calls to Voters and Learners without allocating, but non-obviousness of this is not worth it. Release note: None
2d5d653
to
2059495
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.
Reviewable status: complete! 0 of 0 LGTMs obtained (and 1 stale) (waiting on @danhhz, @nvanbenschoten, and @tbg)
pkg/roachpb/metadata_replicas.go, line 52 at r1 (raw file):
Previously, tbg (Tobias Grieger) wrote…
Can't this just be the same underlying type now?
type ReplicaDescriptors []ReplicaDescriptor
My understanding is there's no overhead to the struct as long as the only field is the wrapped slice and I like making users go through the abstraction. If it was just a type alias for the slice, even users external to the package could simply cast it
pkg/roachpb/metadata_replicas.go, line 170 at r1 (raw file):
Previously, nvanbenschoten (Nathan VanBenschoten) wrote…
Should we add a fast-path here as well? Most of the time we expect no LEARNERS, right? I guess that would be equivalent to not pre-allocating this slice:
var learners []ReplicaDesciptor
You might be worried about the potential for repeat allocations if we do that, in which case I'd still make the allocation lazy:
var learners []ReplicaDesciptor for i := range d.wrapped { if d.wrapped[i].GetType() == ReplicaType_LEARNER { if learners == nil { learners = make([]ReplicaDescriptor, 0, len(d.wrapped)-i) ...
Done
TFTRs! bors r=tbg,nvanbenschoten |
39489: roachpb: stop mutating RangeDescriptor when Replicas is called r=tbg,nvanbenschoten a=danhhz It was previously sorting the InternalReplicas field so we could serve calls to Voters and Learners without allocating, but non-obviousness of this is not worth it. Release note: None Co-authored-by: Daniel Harrison <[email protected]>
Build succeeded |
It was previously sorting the InternalReplicas field so we could serve
calls to Voters and Learners without allocating, but non-obviousness of
this is not worth it.
Release note: None