github.com/koomox/wireguard-go@v0.0.0-20230722134753-17a50b2f22a3/device/pools_test.go (about)

     1  /* SPDX-License-Identifier: MIT
     2   *
     3   * Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
     4   */
     5  
     6  package device
     7  
     8  import (
     9  	"math/rand"
    10  	"runtime"
    11  	"sync"
    12  	"sync/atomic"
    13  	"testing"
    14  	"time"
    15  )
    16  
    17  func TestWaitPool(t *testing.T) {
    18  	t.Skip("Currently disabled")
    19  	var wg sync.WaitGroup
    20  	var trials atomic.Int32
    21  	startTrials := int32(100000)
    22  	if raceEnabled {
    23  		// This test can be very slow with -race.
    24  		startTrials /= 10
    25  	}
    26  	trials.Store(startTrials)
    27  	workers := runtime.NumCPU() + 2
    28  	if workers-4 <= 0 {
    29  		t.Skip("Not enough cores")
    30  	}
    31  	p := NewWaitPool(uint32(workers-4), func() any { return make([]byte, 16) })
    32  	wg.Add(workers)
    33  	var max atomic.Uint32
    34  	updateMax := func() {
    35  		count := p.count.Load()
    36  		if count > p.max {
    37  			t.Errorf("count (%d) > max (%d)", count, p.max)
    38  		}
    39  		for {
    40  			old := max.Load()
    41  			if count <= old {
    42  				break
    43  			}
    44  			if max.CompareAndSwap(old, count) {
    45  				break
    46  			}
    47  		}
    48  	}
    49  	for i := 0; i < workers; i++ {
    50  		go func() {
    51  			defer wg.Done()
    52  			for trials.Add(-1) > 0 {
    53  				updateMax()
    54  				x := p.Get()
    55  				updateMax()
    56  				time.Sleep(time.Duration(rand.Intn(100)) * time.Microsecond)
    57  				updateMax()
    58  				p.Put(x)
    59  				updateMax()
    60  			}
    61  		}()
    62  	}
    63  	wg.Wait()
    64  	if max.Load() != p.max {
    65  		t.Errorf("Actual maximum count (%d) != ideal maximum count (%d)", max, p.max)
    66  	}
    67  }
    68  
    69  func BenchmarkWaitPool(b *testing.B) {
    70  	var wg sync.WaitGroup
    71  	var trials atomic.Int32
    72  	trials.Store(int32(b.N))
    73  	workers := runtime.NumCPU() + 2
    74  	if workers-4 <= 0 {
    75  		b.Skip("Not enough cores")
    76  	}
    77  	p := NewWaitPool(uint32(workers-4), func() any { return make([]byte, 16) })
    78  	wg.Add(workers)
    79  	b.ResetTimer()
    80  	for i := 0; i < workers; i++ {
    81  		go func() {
    82  			defer wg.Done()
    83  			for trials.Add(-1) > 0 {
    84  				x := p.Get()
    85  				time.Sleep(time.Duration(rand.Intn(100)) * time.Microsecond)
    86  				p.Put(x)
    87  			}
    88  		}()
    89  	}
    90  	wg.Wait()
    91  }
    92  
    93  func BenchmarkWaitPoolEmpty(b *testing.B) {
    94  	var wg sync.WaitGroup
    95  	var trials atomic.Int32
    96  	trials.Store(int32(b.N))
    97  	workers := runtime.NumCPU() + 2
    98  	if workers-4 <= 0 {
    99  		b.Skip("Not enough cores")
   100  	}
   101  	p := NewWaitPool(0, func() any { return make([]byte, 16) })
   102  	wg.Add(workers)
   103  	b.ResetTimer()
   104  	for i := 0; i < workers; i++ {
   105  		go func() {
   106  			defer wg.Done()
   107  			for trials.Add(-1) > 0 {
   108  				x := p.Get()
   109  				time.Sleep(time.Duration(rand.Intn(100)) * time.Microsecond)
   110  				p.Put(x)
   111  			}
   112  		}()
   113  	}
   114  	wg.Wait()
   115  }
   116  
   117  func BenchmarkSyncPool(b *testing.B) {
   118  	var wg sync.WaitGroup
   119  	var trials atomic.Int32
   120  	trials.Store(int32(b.N))
   121  	workers := runtime.NumCPU() + 2
   122  	if workers-4 <= 0 {
   123  		b.Skip("Not enough cores")
   124  	}
   125  	p := sync.Pool{New: func() any { return make([]byte, 16) }}
   126  	wg.Add(workers)
   127  	b.ResetTimer()
   128  	for i := 0; i < workers; i++ {
   129  		go func() {
   130  			defer wg.Done()
   131  			for trials.Add(-1) > 0 {
   132  				x := p.Get()
   133  				time.Sleep(time.Duration(rand.Intn(100)) * time.Microsecond)
   134  				p.Put(x)
   135  			}
   136  		}()
   137  	}
   138  	wg.Wait()
   139  }