forked from TrueCloudLab/hrw
[#8] hrw: Do not allocate for swap()/less() helpers
``` 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 <e.stratonikov@yadro.com>
This commit is contained in:
parent
c52f74d8e1
commit
266da7c69a
1 changed files with 26 additions and 18 deletions
44
hrw.go
44
hrw.go
|
@ -21,6 +21,12 @@ type (
|
||||||
less func(i, j int) bool
|
less func(i, j int) bool
|
||||||
swap func(i, j int)
|
swap func(i, j int)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hasherSorter[T Hasher, N interface{ ~uint64 | ~float64 }] struct {
|
||||||
|
slice []T
|
||||||
|
dist []N
|
||||||
|
asc bool
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Boundaries of valid normalized weights
|
// 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) Less(i, j int) bool { return s.less(i, j) }
|
||||||
func (s *sorter) Swap(i, j int) { s.swap(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 {
|
func distance(x uint64, y uint64) uint64 {
|
||||||
acc := x ^ y
|
acc := x ^ y
|
||||||
// here used mmh3 64 bit finalizer
|
// 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]
|
dist[i] = float64(^uint64(0)-d) * weights[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Sort(&sorter{
|
sort.Sort(&hasherSorter[T, float64]{
|
||||||
l: len(slice),
|
slice: slice,
|
||||||
swap: func(i, j int) {
|
dist: dist,
|
||||||
slice[i], slice[j] = slice[j], slice[i]
|
asc: false,
|
||||||
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
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// sortHasherByDistance is similar to sortByDistance but accepts slice directly.
|
// sortHasherByDistance is similar to sortByDistance but accepts slice directly.
|
||||||
func sortHasherByDistance[T Hasher](slice []T, byIndex bool, dist []uint64) {
|
func sortHasherByDistance[T Hasher](slice []T, byIndex bool, dist []uint64) {
|
||||||
sort.Sort(&sorter{
|
sort.Sort(&hasherSorter[T, uint64]{
|
||||||
l: len(slice),
|
slice: slice,
|
||||||
swap: func(i, j int) {
|
dist: dist,
|
||||||
slice[i], slice[j] = slice[j], slice[i]
|
asc: true,
|
||||||
dist[i], dist[j] = dist[j], dist[i]
|
|
||||||
},
|
|
||||||
less: func(i, j int) bool {
|
|
||||||
return dist[i] < dist[j]
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue