-
Notifications
You must be signed in to change notification settings - Fork 21.5k
Use slices package for most sorting
#27474
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
Use slices package for most sorting
#27474
Conversation
…node, neturil; use slices.Sort instead of sort.Strings
…t method for sorting
| sigs = append(sigs, sig) | ||
| } | ||
| sort.Sort(signersAscending(sigs)) | ||
| slices.SortFunc(sigs, func(a, b common.Address) bool { |
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.
I think you could reasonably define a Less function on common.Address. I decided not to do so in this PR, but something to consider for the maintainers.
|
|
||
| // Swap swaps the elements with indexes i and j. | ||
| func (hs hashes) Swap(i, j int) { hs[i], hs[j] = hs[j], hs[i] } | ||
| func hashesLess(a, b common.Hash) bool { |
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.
Similar to common.Address, maintainers might consider whether it would be reasonable to implement Less on common.Hash
|
The numbers are pretty impressive! The PR is too huge by touching lots of files. Will discuss it in our PR triage. |
|
Another variant of the benchmark: func BenchmarkSliceSort(b *testing.B) {
sizes := []int{8 /*16, 32, */, 64 /*128, 256, */, 512 /*1024, 2048, */, 4096, 8192}
for _, size := range sizes {
src := make([]byte, size)
rand.Read(src)
data := make([]byte, size)
b.Run(fmt.Sprintf("slices.Sort size=%d", size),
func(b *testing.B) {
for i := 0; i < b.N; i++ {
copy(data, src)
slices.Sort(data)
}
},
)
b.Run(fmt.Sprintf("slices.SortFunc size=%d", size),
func(b *testing.B) {
for i := 0; i < b.N; i++ {
copy(data, src)
//slices.Sort(data)
slices.SortFunc(data, func(a, b byte) bool {
return a < b
})
}
},
)
b.Run(fmt.Sprintf("sort.Slice size=%d", size),
func(b *testing.B) {
for i := 0; i < b.N; i++ {
copy(data, src)
sort.Slice(data, func(i, j int) bool {
return data[i] < data[j]
})
}
},
)
}
}Results This is worth pursuing, but perhaps it would be better to bite off smaller chunks. We've done so before on larger prs that touch everything (e.g. when converting from the form |
|
@holiman Sure I'll close this PR and open a bunch of smaller ones that only touch 1 or 2 packages |
This PR makes changes many, but not all, uses of sorting functions from the
sortpackage to use theslicespackage instead.sort.Sortrelies onsort.Interface, which often requires implementing structs whose sole purpose is to implement this interface. This change allows for the removal of several such structs (e.g.type authors []stringinbuild/update-license.go)sort.Sliceuses reflection internally, which is slow. Usingslices.Sortis faster. This benchmark:gives these results on my machine:
I didn't replace all usage of
sort.Sort. Namely, I left it in places where:sort.Interfacealso implementsheap.Interface(so it can't be removed anyway.)capacitySortineth/protocols/snap/sync.go)