perf(spanner): improve mutationProto allocations and performance#12740
perf(spanner): improve mutationProto allocations and performance#12740
Conversation
|
The benchmark results indicate a significant performance improvement. The mutationsProto function is now approximately 81% faster, uses 57% less memory, and makes 16% fewer memory allocations on average. |
|
@codyoss quick review here is really appreciated. |
| if rand.Intn(nonInsertCount) == 0 { | ||
| selectedNonInsertIdx = i | ||
| } |
There was a problem hiding this comment.
I like how we're avoiding allocs now, but one improvement here is to avoid doing the rand.Intn() in a tightloop. Would you consider doing an extra loop through the mutations? I'd imagine that may actually result in better performance since rand methods are relatively slow.
| if rand.Intn(nonInsertCount) == 0 { | |
| selectedNonInsertIdx = i | |
| } |
and then later:
if nonInsertCount > 0 {
selectedNonInsertIdx := rand.Intn(nonInsertCount)
var selectedMutation *Mutation
for i, outM := range out {
inM := ms[i]
if inM.op == opInsert {
if selectedNonInsertIdx == 0 {
selectedMutation = outM
break
}
selectedNonInsertIdx--
}
return out, selectedMutation, nil
}
}
There was a problem hiding this comment.
Actually, tried out the diff on my local branch and it didn't seem to be any faster. So nevermind here.
| if rand.Intn(nonInsertCount) == 0 { | ||
| selectedNonInsertIdx = i | ||
| } |
There was a problem hiding this comment.
Actually, tried out the diff on my local branch and it didn't seem to be any faster. So nevermind here.
| if rand.Intn(nonInsertCount) == 0 { | ||
| selectedNonInsertIdx = i | ||
| } |
There was a problem hiding this comment.
nit: at first glance it's a bit surprising that this ends up being a uniform distribution, so perhaps a comment can help here:
| if rand.Intn(nonInsertCount) == 0 { | |
| selectedNonInsertIdx = i | |
| } | |
| // Pick a non-insert mutation uniformly at random. | |
| if rand.Intn(nonInsertCount) == 0 { | |
| selectedNonInsertIdx = i | |
| } |
| } | ||
|
|
||
| return l, nil, nil | ||
| return out, nil, nil |
There was a problem hiding this comment.
This point will never be reached, right? Because we always have:
- An empty input slice of mutations, which causes an empty return
- At least one non-insert mutation.
- Or one insert mutation.
There was a problem hiding this comment.
Yes, this is here because Golang expects a return at the end of method.
Fixes: #12680