Browse Source

pkg/idutil: use count field as atomic variable

Use atomic.AddUint64 instead of mutex lock to inc count field.

Bench result:
benchmark           old ns/op     new ns/op     delta
BenchmarkNext-4     163           26.3          -83.87%
lorneli 7 years ago
parent
commit
54827d47ee
2 changed files with 12 additions and 6 deletions
  1. 3 6
      pkg/idutil/id.go
  2. 9 0
      pkg/idutil/id_test.go

+ 3 - 6
pkg/idutil/id.go

@@ -18,7 +18,7 @@ package idutil
 
 import (
 	"math"
-	"sync"
+	"sync/atomic"
 	"time"
 )
 
@@ -47,7 +47,6 @@ const (
 // id generated after restart is unique because etcd throughput is <<
 // 256req/ms(250k reqs/second).
 type Generator struct {
-	mu sync.Mutex
 	// high order 2 bytes
 	prefix uint64
 	// low order 6 bytes
@@ -66,10 +65,8 @@ func NewGenerator(memberID uint16, now time.Time) *Generator {
 
 // Next generates a id that is unique.
 func (g *Generator) Next() uint64 {
-	g.mu.Lock()
-	defer g.mu.Unlock()
-	g.suffix++
-	id := g.prefix | lowbit(g.suffix, suffixLen)
+	suffix := atomic.AddUint64(&g.suffix, 1)
+	id := g.prefix | lowbit(suffix, suffixLen)
 	return id
 }
 

+ 9 - 0
pkg/idutil/id_test.go

@@ -53,3 +53,12 @@ func TestNext(t *testing.T) {
 		}
 	}
 }
+
+func BenchmarkNext(b *testing.B) {
+	g := NewGenerator(0x12, time.Now())
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		g.Next()
+	}
+}