From 266da7c69ac09516384d50fd9b53205316607e9f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 1 Jun 2023 20:48:47 +0300 Subject: [PATCH] [#8] hrw: Do not allocate for swap()/less() helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ``` goos: linux goarch: amd64 pkg: git.frostfs.info/TrueCloudLab/hrw cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz │ 4 │ 5 │ │ sec/op │ sec/op vs base │ SortHashersByValue_Typed_fnv_10-8 309.2n ± 2% 294.4n ± 1% -4.75% (p=0.000 n=10) SortHashersByValue_Typed_fnv_100-8 2.306µ ± 1% 2.549µ ± 1% +10.54% (p=0.000 n=10) SortHashersByValue_Typed_fnv_1000-8 21.73µ ± 1% 24.80µ ± 3% +14.14% (p=0.000 n=10) SortHashersByWeightValueTyped_fnv_10-8 347.1n ± 1% 334.8n ± 2% -3.56% (p=0.000 n=10) SortHashersByWeightValueTyped_fnv_100-8 2.668µ ± 1% 2.954µ ± 3% +10.72% (p=0.000 n=10) SortHashersByWeightValueTyped_fnv_1000-8 2.673µ ± 1% 2.957µ ± 4% +10.63% (p=0.000 n=10) geomean 1.836µ 1.947µ +6.01% │ 4 │ 5 │ │ B/op │ B/op vs base │ SortHashersByValue_Typed_fnv_10-8 216.0 ± 0% 144.0 ± 0% -33.33% (p=0.000 n=10) SortHashersByValue_Typed_fnv_100-8 1032.0 ± 0% 960.0 ± 0% -6.98% (p=0.000 n=10) SortHashersByValue_Typed_fnv_1000-8 8.133Ki ± 0% 8.062Ki ± 0% -0.86% (p=0.000 n=10) SortHashersByWeightValueTyped_fnv_10-8 216.0 ± 0% 144.0 ± 0% -33.33% (p=0.000 n=10) SortHashersByWeightValueTyped_fnv_100-8 1032.0 ± 0% 960.0 ± 0% -6.98% (p=0.000 n=10) SortHashersByWeightValueTyped_fnv_1000-8 1032.0 ± 0% 960.0 ± 0% -6.98% (p=0.000 n=10) geomean 867.8 730.1 -15.87% │ 4 │ 5 │ │ allocs/op │ allocs/op vs base │ SortHashersByValue_Typed_fnv_10-8 4.000 ± 0% 2.000 ± 0% -50.00% (p=0.000 n=10) SortHashersByValue_Typed_fnv_100-8 4.000 ± 0% 2.000 ± 0% -50.00% (p=0.000 n=10) SortHashersByValue_Typed_fnv_1000-8 4.000 ± 0% 2.000 ± 0% -50.00% (p=0.000 n=10) SortHashersByWeightValueTyped_fnv_10-8 4.000 ± 0% 2.000 ± 0% -50.00% (p=0.000 n=10) SortHashersByWeightValueTyped_fnv_100-8 4.000 ± 0% 2.000 ± 0% -50.00% (p=0.000 n=10) SortHashersByWeightValueTyped_fnv_1000-8 4.000 ± 0% 2.000 ± 0% -50.00% (p=0.000 n=10) geomean 4.000 2.000 -50.00% ``` Signed-off-by: Evgenii Stratonikov --- hrw.go | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/hrw.go b/hrw.go index c874917..9059636 100644 --- a/hrw.go +++ b/hrw.go @@ -21,6 +21,12 @@ type ( less func(i, j int) bool swap func(i, j int) } + + hasherSorter[T Hasher, N interface{ ~uint64 | ~float64 }] struct { + slice []T + dist []N + asc bool + } ) // Boundaries of valid normalized weights @@ -33,6 +39,18 @@ func (s *sorter) Len() int { return s.l } func (s *sorter) Less(i, j int) bool { return s.less(i, j) } func (s *sorter) Swap(i, j int) { s.swap(i, j) } +func (s *hasherSorter[T, N]) Len() int { return len(s.slice) } +func (s *hasherSorter[T, N]) Less(i, j int) bool { + if s.asc { + return s.dist[i] < s.dist[j] + } + return s.dist[i] > s.dist[j] +} +func (s *hasherSorter[T, N]) Swap(i, j int) { + s.slice[i], s.slice[j] = s.slice[j], s.slice[i] + s.dist[i], s.dist[j] = s.dist[j], s.dist[i] +} + func distance(x uint64, y uint64) uint64 { acc := x ^ y // here used mmh3 64 bit finalizer @@ -128,29 +146,19 @@ func SortHasherSliceByWeightValue[T Hasher](slice []T, weights []float64, hash u dist[i] = float64(^uint64(0)-d) * weights[i] } - sort.Sort(&sorter{ - l: len(slice), - swap: func(i, j int) { - slice[i], slice[j] = slice[j], slice[i] - dist[i], dist[j] = dist[j], dist[i] - }, - less: func(i, j int) bool { - return dist[i] > dist[j] // higher distance must be placed lower to be first - }, + sort.Sort(&hasherSorter[T, float64]{ + slice: slice, + dist: dist, + asc: false, }) } // sortHasherByDistance is similar to sortByDistance but accepts slice directly. func sortHasherByDistance[T Hasher](slice []T, byIndex bool, dist []uint64) { - sort.Sort(&sorter{ - l: len(slice), - swap: func(i, j int) { - slice[i], slice[j] = slice[j], slice[i] - dist[i], dist[j] = dist[j], dist[i] - }, - less: func(i, j int) bool { - return dist[i] < dist[j] - }, + sort.Sort(&hasherSorter[T, uint64]{ + slice: slice, + dist: dist, + asc: true, }) }