diff --git a/go.mod b/go.mod index 2532af8..955f0ed 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/TrueCloudLab/frostfs-api-go/v2 v2.0.0-20221212144048-1351b6656d68 github.com/TrueCloudLab/frostfs-contract v0.0.0-20221213081248-6c805c1b4e42 - github.com/TrueCloudLab/hrw v1.1.0 + github.com/TrueCloudLab/hrw v1.1.1-0.20230227111858-79b208bebf52 github.com/TrueCloudLab/tzhash v1.7.0 github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12 github.com/google/uuid v1.3.0 diff --git a/go.sum b/go.sum index e5f78a0..269dc6f 100644 Binary files a/go.sum and b/go.sum differ diff --git a/netmap/netmap.go b/netmap/netmap.go index 75451f0..2626ad9 100644 --- a/netmap/netmap.go +++ b/netmap/netmap.go @@ -152,7 +152,7 @@ func (m NetMap) PlacementVectors(vectors [][]NodeInfo, pivot []byte) ([][]NodeIn for i := range vectors { result[i] = make([]NodeInfo, len(vectors[i])) copy(result[i], vectors[i]) - hrw.SortSliceByWeightValue(result[i], nodes(result[i]).weights(wf), h) + hrw.SortHasherSliceByWeightValue(result[i], nodes(result[i]).weights(wf), h) } return result, nil diff --git a/netmap/node_info.go b/netmap/node_info.go index 42adffd..e7e30ce 100644 --- a/netmap/node_info.go +++ b/netmap/node_info.go @@ -25,7 +25,8 @@ import ( // // Instances can be created using built-in var declaration. type NodeInfo struct { - m netmap.NodeInfo + m netmap.NodeInfo + hash uint64 } // reads NodeInfo from netmap.NodeInfo message. If checkFieldPresence is set, @@ -86,6 +87,7 @@ func (x *NodeInfo) readFromV2(m netmap.NodeInfo, checkFieldPresence bool) error } x.m = m + x.hash = hrw.Hash(binPublicKey) return nil } @@ -167,6 +169,7 @@ func (x *NodeInfo) UnmarshalJSON(data []byte) error { // See also PublicKey. func (x *NodeInfo) SetPublicKey(key []byte) { x.m.SetPublicKey(key) + x.hash = hrw.Hash(x.m.GetPublicKey()) } // PublicKey returns value set using SetPublicKey. @@ -233,6 +236,9 @@ var _ hrw.Hasher = NodeInfo{} // Hash is needed to support weighted HRW therefore sort function sorts nodes // based on their public key. Hash isn't expected to be used directly. func (x NodeInfo) Hash() uint64 { + if x.hash != 0 { + return x.hash + } return hrw.Hash(x.m.GetPublicKey()) } diff --git a/netmap/selector.go b/netmap/selector.go index 370cf10..3e1d321 100644 --- a/netmap/selector.go +++ b/netmap/selector.go @@ -108,7 +108,7 @@ func (c *context) getSelection(p PlacementPolicy, s netmap.Selector) ([]nodes, e weights[i] = calcBucketWeight(res[i], newMeanIQRAgg(), c.weightFunc) } - hrw.SortSliceByWeightValue(res, weights, c.hrwSeedHash) + hrw.SortHasherSliceByWeightValue(res, weights, c.hrwSeedHash) } if s.GetAttribute() == "" { @@ -164,7 +164,7 @@ func (c *context) getSelectionBase(subnetID subnetid.ID, s netmap.Selector) []no if len(c.hrwSeed) != 0 { for i := range result { - hrw.SortSliceByWeightValue(result[i].nodes, result[i].nodes.weights(c.weightFunc), c.hrwSeedHash) + hrw.SortHasherSliceByWeightValue(result[i].nodes, result[i].nodes.weights(c.weightFunc), c.hrwSeedHash) } } diff --git a/netmap/selector_test.go b/netmap/selector_test.go index 96d9b21..936cfed 100644 --- a/netmap/selector_test.go +++ b/netmap/selector_test.go @@ -50,7 +50,7 @@ func BenchmarkHRWSort(b *testing.B) { copy(realNodes, vectors) b.StartTimer() - hrw.SortSliceByValue(realNodes, pivot) + hrw.SortHasherSliceByValue(realNodes, pivot) } }) b.Run("only sort by index", func(b *testing.B) { @@ -72,7 +72,7 @@ func BenchmarkHRWSort(b *testing.B) { copy(realNodes, vectors) b.StartTimer() - hrw.SortSliceByWeightValue(realNodes, weights, pivot) + hrw.SortHasherSliceByWeightValue(realNodes, weights, pivot) } }) b.Run("sort by ID, then by index (deterministic)", func(b *testing.B) {