From a0de29d9aef7c60616d0c438857fafa4dca7798a Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Thu, 1 Aug 2024 00:28:51 -0400 Subject: [PATCH] Simplify IDGenerator and reduce collission rate Since offset is always truncated to s.numBuckets, atomic.Add could be used instead of atomic.Load + atomic.Swap Also offsetting bucket by 1 does not give lot's of space for collission avoidance. If first call hits bucket that is fully in use, second call going to share same bucket with first call. --- internal/streams/streams.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/internal/streams/streams.go b/internal/streams/streams.go index 7e502c2cc..b31a96979 100644 --- a/internal/streams/streams.go +++ b/internal/streams/streams.go @@ -50,13 +50,8 @@ func streamFromBucket(bucket, streamInBucket int) int { } func (s *IDGenerator) GetStream() (int, bool) { - // based closely on the java-driver stream ID generator - // avoid false sharing subsequent requests. - offset := atomic.LoadUint32(&s.offset) - for !atomic.CompareAndSwapUint32(&s.offset, offset, (offset+1)%s.numBuckets) { - offset = atomic.LoadUint32(&s.offset) - } - offset = (offset + 1) % s.numBuckets + // Reduce collisions by offsetting the starting point + offset := atomic.AddUint32(&s.offset, 1) for i := uint32(0); i < s.numBuckets; i++ { pos := int((i + offset) % s.numBuckets)