Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 15 additions & 10 deletions pool/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,16 +337,16 @@ func (p *ShardedPool[T, P]) getShard() (*Shard[T, P], int) {
id := runtimeProcPin()
runtimeProcUnpin()

return p.Shards[id&(shardMask)], id // ensure we don't get "index out of bounds error" if number of P's changes
return p.Shards[id&(shardMask)], id
}

// Get returns an object from the pool or creates a new one.
// Returns nil if MaxPoolSize is set, reached, and no reusable objects are available.
func (p *ShardedPool[T, P]) Get() P {
// INLINED: Direct shard selection without function call
id := runtimeProcPin()
shard := p.Shards[id&shardMask]
runtimeProcUnpin()
shard := p.Shards[id&(numShards-1)]

// Fast path: check single object first
if single := P(shard.Single.Load()); single != nil {
Expand All @@ -356,7 +356,6 @@ func (p *ShardedPool[T, P]) Get() P {
}
}

// INLINED: Direct object retrieval without function call
// Fast path: try to get object from shard
for {
oldHead := P(shard.Head.Load())
Expand All @@ -366,17 +365,16 @@ func (p *ShardedPool[T, P]) Get() P {

next := oldHead.GetNext()
if shard.Head.CompareAndSwap(oldHead, next) {
// INLINED: Direct usage increment without virtual method call
oldHead.IncrementUsage()
return oldHead
}
// CAS failed, retry
}

// INLINED: Direct allocation path without function calls
// Direct allocation path
if !p.cfg.Growth.Enable {
obj := P(p.cfg.Allocator())
obj.IncrementUsage() // Direct field access
obj.IncrementUsage()
p.CurrentPoolLength.Add(1)
return obj
}
Expand All @@ -386,7 +384,7 @@ func (p *ShardedPool[T, P]) Get() P {
}

obj := P(p.cfg.Allocator())
obj.IncrementUsage() // Direct field access
obj.IncrementUsage()
p.CurrentPoolLength.Add(1)
return obj
}
Expand Down Expand Up @@ -460,17 +458,24 @@ func (p *ShardedPool[T, P]) Put(obj P) {
p.cfg.Cleaner(obj)

id := runtimeProcPin()
shard := p.Shards[id&shardMask]
runtimeProcUnpin()
shard := p.Shards[id&(numShards-1)]

// Fast path: try single object first
if shard.Single.CompareAndSwap(nil, obj) {
return
}

for {
oldHead := P(shard.Head.Load())
// Single CAS attempt for the common case
oldHead := P(shard.Head.Load())
if shard.Head.CompareAndSwap(oldHead, obj) {
obj.SetNext(oldHead)
return
}

// Fallback to retry loop only if needed
for {
oldHead = P(shard.Head.Load())
if shard.Head.CompareAndSwap(oldHead, obj) {
obj.SetNext(oldHead)
return
Expand Down
Loading