From 34d0cccefd7bff28299b137ab46d3143d1778758 Mon Sep 17 00:00:00 2001 From: Tony Chen Date: Fri, 28 Jan 2022 15:05:26 +0800 Subject: [PATCH] fix: allocates new objects each time (#1802) --- selector/p2c/p2c.go | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/selector/p2c/p2c.go b/selector/p2c/p2c.go index c76db651d..21a2199b8 100644 --- a/selector/p2c/p2c.go +++ b/selector/p2c/p2c.go @@ -3,6 +3,7 @@ package p2c import ( "context" "math/rand" + "sync" "sync/atomic" "time" @@ -40,15 +41,17 @@ func New(opts ...Option) selector.Selector { // Balancer is p2c selector. type Balancer struct { - r *rand.Rand - lk int64 + mu sync.Mutex + r *rand.Rand + picked int64 } // choose two distinct nodes. func (s *Balancer) prePick(nodes []selector.WeightedNode) (nodeA selector.WeightedNode, nodeB selector.WeightedNode) { - source := rand.NewSource(time.Now().UnixNano()) - a := rand.New(source).Intn(len(nodes)) - b := rand.New(source).Intn(len(nodes) - 1) + s.mu.Lock() + a := s.r.Intn(len(nodes)) + b := s.r.Intn(len(nodes) - 1) + s.mu.Unlock() if b >= a { b = b + 1 } @@ -60,7 +63,8 @@ func (s *Balancer) prePick(nodes []selector.WeightedNode) (nodeA selector.Weight func (s *Balancer) Pick(ctx context.Context, nodes []selector.WeightedNode) (selector.WeightedNode, selector.DoneFunc, error) { if len(nodes) == 0 { return nil, nil, selector.ErrNoAvailable - } else if len(nodes) == 1 { + } + if len(nodes) == 1 { done := nodes[0].Pick() return nodes[0], done, nil } @@ -76,9 +80,9 @@ func (s *Balancer) Pick(ctx context.Context, nodes []selector.WeightedNode) (sel // If the failed node has never been selected once during forceGap, it is forced to be selected once // Take advantage of forced opportunities to trigger updates of success rate and delay - if upc.PickElapsed() > forcePick && atomic.CompareAndSwapInt64(&s.lk, 0, 1) { + if upc.PickElapsed() > forcePick && atomic.CompareAndSwapInt64(&s.picked, 0, 1) { pc = upc - atomic.StoreInt64(&s.lk, 0) + atomic.StoreInt64(&s.picked, 0) } done := pc.Pick() return pc, done, nil