diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c88aff0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.idea +*.exe +demo +etc/*.conf +etc/*.cfg \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..76a0b56 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module github.com/joykk/hashring + +go 1.13 + +require github.com/sirupsen/logrus v1.4.2 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..706fe8d --- /dev/null +++ b/go.sum @@ -0,0 +1,13 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/hashring.go b/hashring.go index 4ac0ffd..d6d22a9 100644 --- a/hashring.go +++ b/hashring.go @@ -88,8 +88,12 @@ func (h *HashRing) generate() { } totalVirtualSpots := h.virualSpots * len(h.weights) - h.nodes = nodesArray{} + var nodeLen, nodeIndex int64 + for _, w := range h.weights { + nodeLen += int64(math.Floor(float64(w) / float64(totalW) * float64(totalVirtualSpots))) + } + h.nodes = make(nodesArray, nodeLen) for nodeKey, w := range h.weights { spots := int(math.Floor(float64(w) / float64(totalW) * float64(totalVirtualSpots))) for i := 1; i <= spots; i++ { @@ -100,7 +104,8 @@ func (h *HashRing) generate() { nodeKey: nodeKey, spotValue: genValue(hashBytes[6:10]), } - h.nodes = append(h.nodes, n) + h.nodes[nodeIndex] = n + nodeIndex += 1 hash.Reset() } } diff --git a/hashring_test.go b/hashring_test.go index c92fdfc..5c919a0 100644 --- a/hashring_test.go +++ b/hashring_test.go @@ -1,8 +1,12 @@ package hashring import ( - // "fmt" + "fmt" + "regexp" + "runtime" + "strconv" "testing" + "time" ) const ( @@ -22,7 +26,6 @@ func getNodesCount(nodes nodesArray) (int, int, int) { } if node.nodeKey == node2 { node2Count += 1 - } if node.nodeKey == node3 { node3Count += 1 @@ -82,3 +85,32 @@ func TestHash(t *testing.T) { t.Logf("len of nodes is %v after AddNode node1:%v, node2:%v, node3:%v", len(hash.nodes), c1, c2, c3) } + +func TimeTrack(start time.Time) { + elapsed := time.Since(start) + + // Skip this function, and fetch the PC and file for its parent. + pc, _, _, _ := runtime.Caller(1) + + // Retrieve a function object this functions parent. + funcObj := runtime.FuncForPC(pc) + + // Regex to extract just the function name (and not the module path). + runtimeFunc := regexp.MustCompile(`^.*\.(.*)$`) + name := runtimeFunc.ReplaceAllString(funcObj.Name(), "$1") + + fmt.Printf("TimeTrack funcName:%s elapsed:%s \n", name, elapsed) +} + +func TestSpeed(t *testing.T) { + // node=1000 v=50000 on 16GB/win10/i7 init 35s + defer TimeTrack(time.Now()) + nodeWeight := make(map[string]int) + for i := 0; i < 1000; i += 1 { + nodeWeight[strconv.Itoa(i)] = 1 + } + vitualSpots := 50000 + hash := NewHashRing(vitualSpots) + + hash.AddNodes(nodeWeight) +}