From 2671bfe3eda649b25745de71318044dc766ab362 Mon Sep 17 00:00:00 2001 From: Matthew Rothenberg Date: Sat, 30 Dec 2023 12:35:13 -0500 Subject: [PATCH] perf: replace sort.Slice with slices.SortFunc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we're already requiring the slices package in stdlib with this refactor, we can utilize this newer function which should be slightly more efficient (and has nicer ergonomics imo). Performs roughly ~11% faster during NewChooser initialization. goos: darwin goarch: arm64 pkg: github.com/mroth/weightedrand/v2 │ v3-dev1.txt │ v3-dev2.txt │ │ sec/op │ sec/op vs base │ NewChooser/size=1e1-8 132.90n ± 0% 70.73n ± 1% -46.78% (p=0.002 n=6) NewChooser/size=1e2-8 472.8n ± 0% 444.1n ± 2% -6.05% (p=0.002 n=6) NewChooser/size=1e3-8 3.412µ ± 0% 3.333µ ± 0% -2.30% (p=0.002 n=6) NewChooser/size=1e4-8 31.03µ ± 0% 30.30µ ± 0% -2.33% (p=0.002 n=6) NewChooser/size=1e5-8 295.9µ ± 0% 291.9µ ± 1% -1.36% (p=0.002 n=6) NewChooser/size=1e6-8 2.843m ± 1% 2.775m ± 1% -2.37% (p=0.002 n=6) NewChooser/size=1e7-8 35.92m ± 1% 32.99m ± 2% -8.16% (p=0.002 n=6) geomean 279.7n 36.41µ -11.60% ¹ ¹ benchmark set differs from baseline; geomeans may not be comparable --- weightedrand.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/weightedrand.go b/weightedrand.go index 09b9042..03648a7 100644 --- a/weightedrand.go +++ b/weightedrand.go @@ -9,11 +9,11 @@ package weightedrand import ( + "cmp" "errors" "math" "math/rand/v2" "slices" - "sort" ) // Choice is a generic wrapper that can be used to add weights for any item. @@ -41,8 +41,8 @@ type Chooser[T any, W integer] struct { // NewChooser initializes a new Chooser for picking from the provided choices. func NewChooser[T any, W integer](choices ...Choice[T, W]) (*Chooser[T, W], error) { - sort.Slice(choices, func(i, j int) bool { - return choices[i].Weight < choices[j].Weight + slices.SortFunc(choices, func(a, b Choice[T, W]) int { + return cmp.Compare(a.Weight, b.Weight) }) totals := make([]uint64, len(choices)) @@ -67,7 +67,6 @@ func NewChooser[T any, W integer](choices ...Choice[T, W]) (*Chooser[T, W], erro return &Chooser[T, W]{data: choices, totals: totals, max: runningTotal}, nil } - // Possible errors returned by NewChooser, preventing the creation of a Chooser // with unsafe runtime states. var (