Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize NewSafeID using atomic #1035

Merged
merged 5 commits into from Feb 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 10 additions & 10 deletions messageID.go
@@ -1,6 +1,6 @@
package slack

import "sync"
import "sync/atomic"

// IDGenerator provides an interface for generating integer ID values.
type IDGenerator interface {
Expand All @@ -11,20 +11,20 @@ type IDGenerator interface {
// concurrent use by multiple goroutines.
func NewSafeID(startID int) IDGenerator {
return &safeID{
nextID: startID,
mutex: &sync.Mutex{},
nextID: int64(startID),
}
}

type safeID struct {
nextID int
mutex *sync.Mutex
nextID int64
}

// make sure safeID implements the IDGenerator interface.
var _ IDGenerator = (*safeID)(nil)

// Next implements IDGenerator.Next.
func (s *safeID) Next() int {
s.mutex.Lock()
defer s.mutex.Unlock()
id := s.nextID
s.nextID++
return id
id := atomic.AddInt64(&s.nextID, 1)

return int(id)
}
46 changes: 46 additions & 0 deletions messageID_test.go
@@ -0,0 +1,46 @@
package slack

import (
"testing"
)

func TestNewSafeID(t *testing.T) {
idgen := NewSafeID(1)
id1 := idgen.Next()
id2 := idgen.Next()
if id1 == id2 {
t.Fatalf("id1 and id2 are same: id1: %d, id2: %d", id1, id2)
}

idgen = NewSafeID(100)
id100 := idgen.Next()
id101 := idgen.Next()
if id2 == id100 {
t.Fatalf("except id2 and id100 not same: id2: %d, id101: %d", id2, id100)
}
if id100 == id101 {
t.Fatalf("id1 and id2 are same: id100: %d, id101: %d", id100, id101)
}
}

var id int

func BenchmarkNewSafeID(b *testing.B) {
b.ReportAllocs()

idgen := NewSafeID(1)
for i := 0; i < b.N; i++ {
id = idgen.Next()
}
}

func BenchmarkNewSafeIDParallel(b *testing.B) {
b.ReportAllocs()

b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
idgen := NewSafeID(1)
id = idgen.Next()
}
})
}