-
Notifications
You must be signed in to change notification settings - Fork 20.2k
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
Use slices
package for most sorting
#27474
Conversation
…node, neturil; use slices.Sort instead of sort.Strings
…t method for sorting
@@ -315,7 +308,9 @@ func (s *Snapshot) signers() []common.Address { | |||
for sig := range s.Signers { | |||
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
sort
package to use theslices
package instead.sort.Sort
relies 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 []string
inbuild/update-license.go
)sort.Slice
uses reflection internally, which is slow. Usingslices.Sort
is 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.Interface
also implementsheap.Interface
(so it can't be removed anyway.)capacitySort
ineth/protocols/snap/sync.go
)