2
0

Add banchmarks with cancelled acquires

This commit is contained in:
Jan Dubsky
2022-09-30 10:02:32 +02:00
committed by Jack Christensen
parent 47b52af713
commit 4fbc609092
3 changed files with 92 additions and 10 deletions
+7
View File
@@ -0,0 +1,7 @@
package puddle
import "context"
func (p *Pool[T]) AcquireRaw(ctx context.Context) (*Resource[T], error) {
return p.acquire(ctx)
}
+7 -1
View File
@@ -293,7 +293,6 @@ func (ctx *valueCancelCtx) Value(key any) any { return ctx.valueCtx.Va
// the problem of it being impossible to create resources when the time to create a resource is greater than any one
// caller of Acquire is willing to wait.
func (p *Pool[T]) Acquire(ctx context.Context) (*Resource[T], error) {
startNano := nanotime()
if doneChan := ctx.Done(); doneChan != nil {
select {
case <-ctx.Done():
@@ -305,6 +304,13 @@ func (p *Pool[T]) Acquire(ctx context.Context) (*Resource[T], error) {
}
}
return p.acquire(ctx)
}
// acquire is a continuation of Acquire function that doesn't check context
// validity. This function exists separatly only for benchmarking purposes.
func (p *Pool[T]) acquire(ctx context.Context) (*Resource[T], error) {
startNano := nanotime()
p.cond.L.Lock()
emptyAcquire := false
+78 -9
View File
@@ -1226,26 +1226,33 @@ func BenchmarkAcquire_ReleaseAfterAcquire(b *testing.B) {
}
}
func BenchmarkAcquire_ReleaseAfterAcquireWithCPUOverload(b *testing.B) {
r := require.New(b)
ctx := context.Background()
pool := benchmarkPool[int32](b)
releaseChan := releaser[int32](b)
func withCPULoad() {
// Multiply by 2 to similate overload of the system.
numGoroutines := runtime.NumCPU() * 2
var wg sync.WaitGroup
for i := 0; i < numGoroutines; i++ {
startChan := make(chan struct{})
wg.Add(1)
go func() {
close(startChan)
wg.Done()
// Similate computationally intensive task.
for j := 0; true; j++ {
}
}()
<-startChan
}
wg.Wait()
}
func BenchmarkAcquire_ReleaseAfterAcquireWithCPULoad(b *testing.B) {
r := require.New(b)
ctx := context.Background()
pool := benchmarkPool[int32](b)
releaseChan := releaser[int32](b)
withCPULoad()
res, err := pool.Acquire(ctx)
r.NoError(err)
// We need to release the last connection. Otherwise the pool.Close()
@@ -1259,3 +1266,65 @@ func BenchmarkAcquire_ReleaseAfterAcquireWithCPUOverload(b *testing.B) {
r.NoError(err)
}
}
func BenchmarkAcquire_MultipleCancelled(b *testing.B) {
const cancelCnt = 64
r := require.New(b)
ctx := context.Background()
pool := benchmarkPool[int32](b)
releaseChan := releaser[int32](b)
cancelCtx, cancel := context.WithCancel(ctx)
cancel()
res, err := pool.Acquire(ctx)
r.NoError(err)
// We need to release the last connection. Otherwise the pool.Close()
// method will block and this function will never return.
defer func() { res.Release() }()
b.ResetTimer()
for i := 0; i < b.N; i++ {
for j := 0; j < cancelCnt; j++ {
_, err = pool.AcquireRaw(cancelCtx)
r.Equal(context.Canceled, err)
}
releaseChan <- res
res, err = pool.Acquire(ctx)
r.NoError(err)
}
}
func BenchmarkAcquire_MultipleCancelledWithCPULoad(b *testing.B) {
const cancelCnt = 3
r := require.New(b)
ctx := context.Background()
pool := benchmarkPool[int32](b)
releaseChan := releaser[int32](b)
cancelCtx, cancel := context.WithCancel(ctx)
cancel()
withCPULoad()
res, err := pool.Acquire(ctx)
r.NoError(err)
// We need to release the last connection. Otherwise the pool.Close()
// method will block and this function will never return.
defer func() { res.Release() }()
b.ResetTimer()
for i := 0; i < b.N; i++ {
for j := 0; j < cancelCnt; j++ {
_, err = pool.AcquireRaw(cancelCtx)
r.Equal(context.Canceled, err)
}
releaseChan <- res
res, err = pool.Acquire(ctx)
r.NoError(err)
}
}