2021-02-02 18:37:49 +01:00
|
|
|
/* SPDX-License-Identifier: MIT
|
|
|
|
*
|
2022-09-20 17:21:32 +02:00
|
|
|
* Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
|
2021-02-02 18:37:49 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
package device
|
|
|
|
|
|
|
|
import (
|
|
|
|
"math/rand"
|
|
|
|
"runtime"
|
|
|
|
"sync"
|
|
|
|
"sync/atomic"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestWaitPool(t *testing.T) {
|
2021-02-22 15:12:03 +01:00
|
|
|
t.Skip("Currently disabled")
|
2021-02-02 18:37:49 +01:00
|
|
|
var wg sync.WaitGroup
|
2022-08-30 16:43:11 +02:00
|
|
|
var trials atomic.Int32
|
|
|
|
startTrials := int32(100000)
|
2021-02-09 17:18:47 +01:00
|
|
|
if raceEnabled {
|
|
|
|
// This test can be very slow with -race.
|
2022-08-30 16:43:11 +02:00
|
|
|
startTrials /= 10
|
2021-02-09 17:18:47 +01:00
|
|
|
}
|
2022-08-30 16:43:11 +02:00
|
|
|
trials.Store(startTrials)
|
2021-02-02 18:37:49 +01:00
|
|
|
workers := runtime.NumCPU() + 2
|
|
|
|
if workers-4 <= 0 {
|
|
|
|
t.Skip("Not enough cores")
|
|
|
|
}
|
2022-03-17 00:40:24 +01:00
|
|
|
p := NewWaitPool(uint32(workers-4), func() any { return make([]byte, 16) })
|
2021-02-02 18:37:49 +01:00
|
|
|
wg.Add(workers)
|
2022-08-30 16:43:11 +02:00
|
|
|
var max atomic.Uint32
|
2021-02-02 18:37:49 +01:00
|
|
|
updateMax := func() {
|
2022-08-30 16:43:11 +02:00
|
|
|
count := p.count.Load()
|
2021-02-02 18:37:49 +01:00
|
|
|
if count > p.max {
|
|
|
|
t.Errorf("count (%d) > max (%d)", count, p.max)
|
|
|
|
}
|
|
|
|
for {
|
2022-08-30 16:43:11 +02:00
|
|
|
old := max.Load()
|
2021-02-02 18:37:49 +01:00
|
|
|
if count <= old {
|
|
|
|
break
|
|
|
|
}
|
2022-08-30 16:43:11 +02:00
|
|
|
if max.CompareAndSwap(old, count) {
|
2021-02-02 18:37:49 +01:00
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for i := 0; i < workers; i++ {
|
|
|
|
go func() {
|
|
|
|
defer wg.Done()
|
2022-08-30 16:43:11 +02:00
|
|
|
for trials.Add(-1) > 0 {
|
2021-02-02 18:37:49 +01:00
|
|
|
updateMax()
|
|
|
|
x := p.Get()
|
|
|
|
updateMax()
|
|
|
|
time.Sleep(time.Duration(rand.Intn(100)) * time.Microsecond)
|
|
|
|
updateMax()
|
|
|
|
p.Put(x)
|
|
|
|
updateMax()
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
wg.Wait()
|
2022-08-30 16:43:11 +02:00
|
|
|
if max.Load() != p.max {
|
2021-02-02 18:37:49 +01:00
|
|
|
t.Errorf("Actual maximum count (%d) != ideal maximum count (%d)", max, p.max)
|
|
|
|
}
|
|
|
|
}
|
2021-02-03 16:54:45 +01:00
|
|
|
|
|
|
|
func BenchmarkWaitPool(b *testing.B) {
|
|
|
|
var wg sync.WaitGroup
|
2022-08-30 16:43:11 +02:00
|
|
|
var trials atomic.Int32
|
|
|
|
trials.Store(int32(b.N))
|
2021-02-03 16:54:45 +01:00
|
|
|
workers := runtime.NumCPU() + 2
|
|
|
|
if workers-4 <= 0 {
|
|
|
|
b.Skip("Not enough cores")
|
|
|
|
}
|
2022-03-17 00:40:24 +01:00
|
|
|
p := NewWaitPool(uint32(workers-4), func() any { return make([]byte, 16) })
|
2021-02-03 16:54:45 +01:00
|
|
|
wg.Add(workers)
|
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < workers; i++ {
|
|
|
|
go func() {
|
|
|
|
defer wg.Done()
|
2022-08-30 16:43:11 +02:00
|
|
|
for trials.Add(-1) > 0 {
|
2021-02-03 16:54:45 +01:00
|
|
|
x := p.Get()
|
|
|
|
time.Sleep(time.Duration(rand.Intn(100)) * time.Microsecond)
|
|
|
|
p.Put(x)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
wg.Wait()
|
2021-02-09 15:09:50 +01:00
|
|
|
}
|
2023-03-02 23:48:02 +01:00
|
|
|
|
|
|
|
func BenchmarkWaitPoolEmpty(b *testing.B) {
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
var trials atomic.Int32
|
|
|
|
trials.Store(int32(b.N))
|
|
|
|
workers := runtime.NumCPU() + 2
|
|
|
|
if workers-4 <= 0 {
|
|
|
|
b.Skip("Not enough cores")
|
|
|
|
}
|
|
|
|
p := NewWaitPool(0, func() any { return make([]byte, 16) })
|
|
|
|
wg.Add(workers)
|
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < workers; i++ {
|
|
|
|
go func() {
|
|
|
|
defer wg.Done()
|
|
|
|
for trials.Add(-1) > 0 {
|
|
|
|
x := p.Get()
|
|
|
|
time.Sleep(time.Duration(rand.Intn(100)) * time.Microsecond)
|
|
|
|
p.Put(x)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
wg.Wait()
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkSyncPool(b *testing.B) {
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
var trials atomic.Int32
|
|
|
|
trials.Store(int32(b.N))
|
|
|
|
workers := runtime.NumCPU() + 2
|
|
|
|
if workers-4 <= 0 {
|
|
|
|
b.Skip("Not enough cores")
|
|
|
|
}
|
|
|
|
p := sync.Pool{New: func() any { return make([]byte, 16) }}
|
|
|
|
wg.Add(workers)
|
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < workers; i++ {
|
|
|
|
go func() {
|
|
|
|
defer wg.Done()
|
|
|
|
for trials.Add(-1) > 0 {
|
|
|
|
x := p.Get()
|
|
|
|
time.Sleep(time.Duration(rand.Intn(100)) * time.Microsecond)
|
|
|
|
p.Put(x)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
wg.Wait()
|
|
|
|
}
|