github.com/dubbogo/gost@v1.14.0/sync/connection_pool_test.go (about)

     1  /*
     2   * Licensed to the Apache Software Foundation (ASF) under one or more
     3   * contributor license agreements.  See the NOTICE file distributed with
     4   * this work for additional information regarding copyright ownership.
     5   * The ASF licenses this file to You under the Apache License, Version 2.0
     6   * (the "License"); you may not use this file except in compliance with
     7   * the License.  You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  
    18  package gxsync
    19  
    20  import (
    21  	"runtime"
    22  	"sync"
    23  	"sync/atomic"
    24  	"testing"
    25  	"time"
    26  )
    27  
    28  import (
    29  	"github.com/stretchr/testify/assert"
    30  )
    31  
    32  func TestConnectionPool(t *testing.T) {
    33  	t.Run("Count", func(t *testing.T) {
    34  		p := NewConnectionPool(WorkerPoolConfig{
    35  			NumWorkers: 100,
    36  			NumQueues:  runtime.NumCPU(),
    37  			QueueSize:  10,
    38  			Logger:     nil,
    39  			Enable:     true,
    40  		})
    41  		var count int64
    42  		wg := new(sync.WaitGroup)
    43  		for i := 1; i <= 100; i++ {
    44  			wg.Add(1)
    45  			value := i
    46  			err := p.Submit(func() {
    47  				defer wg.Done()
    48  				atomic.AddInt64(&count, int64(value))
    49  			})
    50  			assert.Nil(t, err)
    51  		}
    52  		wg.Wait()
    53  		assert.Equal(t, int64(5050), count)
    54  
    55  		p.Close()
    56  	})
    57  
    58  	t.Run("PoolBusyErr", func(t *testing.T) {
    59  		p := NewConnectionPool(WorkerPoolConfig{
    60  			NumWorkers: 1,
    61  			NumQueues:  1,
    62  			QueueSize:  0,
    63  			Logger:     nil,
    64  			Enable:     true,
    65  		})
    66  
    67  		wg := new(sync.WaitGroup)
    68  		wg.Add(1)
    69  		err := p.Submit(func() {
    70  			wg.Wait()
    71  		})
    72  		assert.Nil(t, err)
    73  
    74  		err = p.Submit(func() {})
    75  		assert.Equal(t, PoolBusyErr, err)
    76  
    77  		wg.Done()
    78  		time.Sleep(100 * time.Millisecond)
    79  		err = p.Submit(func() {})
    80  		assert.Nil(t, err)
    81  
    82  		p.Close()
    83  	})
    84  
    85  	t.Run("Close", func(t *testing.T) {
    86  		p := NewConnectionPool(WorkerPoolConfig{
    87  			NumWorkers: runtime.NumCPU(),
    88  			NumQueues:  runtime.NumCPU(),
    89  			QueueSize:  100,
    90  			Enable:     true,
    91  			Logger:     nil,
    92  		})
    93  
    94  		assert.Equal(t, runtime.NumCPU(), int(p.NumWorkers()))
    95  
    96  		p.Close()
    97  		assert.True(t, p.IsClosed())
    98  
    99  		assert.Panics(t, func() {
   100  			_ = p.Submit(func() {})
   101  		})
   102  	})
   103  
   104  	t.Run("BorderCondition", func(t *testing.T) {
   105  		p := NewConnectionPool(WorkerPoolConfig{
   106  			NumWorkers: 0,
   107  			NumQueues:  runtime.NumCPU(),
   108  			Enable:     true,
   109  			QueueSize:  100,
   110  			Logger:     nil,
   111  		})
   112  		assert.Equal(t, 1, int(p.NumWorkers()))
   113  		p.Close()
   114  
   115  		p = NewConnectionPool(WorkerPoolConfig{
   116  			NumWorkers: 1,
   117  			NumQueues:  0,
   118  			Enable:     true,
   119  			QueueSize:  0,
   120  			Logger:     nil,
   121  		})
   122  		err := p.Submit(func() {})
   123  		assert.Nil(t, err)
   124  		p.Close()
   125  
   126  		p = NewConnectionPool(WorkerPoolConfig{
   127  			NumWorkers: 1,
   128  			NumQueues:  1,
   129  			QueueSize:  -1,
   130  			Logger:     nil,
   131  			Enable:     true,
   132  		})
   133  
   134  		err = p.Submit(func() {})
   135  		assert.Nil(t, err)
   136  		p.Close()
   137  	})
   138  
   139  	t.Run("NilTask", func(t *testing.T) {
   140  		p := NewConnectionPool(WorkerPoolConfig{
   141  			NumWorkers: 1,
   142  			NumQueues:  1,
   143  			Enable:     true,
   144  			QueueSize:  0,
   145  			Logger:     nil,
   146  		})
   147  
   148  		err := p.Submit(nil)
   149  		assert.NotNil(t, err)
   150  		p.Close()
   151  	})
   152  
   153  	t.Run("CountTask", func(t *testing.T) {
   154  		p := NewConnectionPool(WorkerPoolConfig{
   155  			NumWorkers: runtime.NumCPU(),
   156  			NumQueues:  runtime.NumCPU(),
   157  			QueueSize:  10,
   158  			Logger:     nil,
   159  			Enable:     true,
   160  		})
   161  
   162  		task, v := newCountTask()
   163  		wg := new(sync.WaitGroup)
   164  		wg.Add(100)
   165  		for i := 0; i < 100; i++ {
   166  			if err := p.Submit(func() {
   167  				defer wg.Done()
   168  				task()
   169  			}); err != nil {
   170  				i--
   171  			}
   172  		}
   173  
   174  		wg.Wait()
   175  		assert.Equal(t, 100, int(*v))
   176  		p.Close()
   177  	})
   178  
   179  	t.Run("CountTaskSync", func(t *testing.T) {
   180  		p := NewConnectionPool(WorkerPoolConfig{
   181  			NumWorkers: runtime.NumCPU(),
   182  			NumQueues:  runtime.NumCPU(),
   183  			QueueSize:  10,
   184  			Logger:     nil,
   185  			Enable:     true,
   186  		})
   187  
   188  		task, v := newCountTask()
   189  		for i := 0; i < 100; i++ {
   190  			err := p.SubmitSync(task)
   191  			assert.Nil(t, err)
   192  		}
   193  
   194  		assert.Equal(t, 100, int(*v))
   195  		p.Close()
   196  	})
   197  }
   198  
   199  func BenchmarkConnectionPool(b *testing.B) {
   200  	p := NewConnectionPool(WorkerPoolConfig{
   201  		NumWorkers: 100,
   202  		NumQueues:  runtime.NumCPU(),
   203  		QueueSize:  100,
   204  		Enable:     true,
   205  		Logger:     nil,
   206  	})
   207  
   208  	b.Run("CountTask", func(b *testing.B) {
   209  		task, _ := newCountTask()
   210  		b.RunParallel(func(pb *testing.PB) {
   211  			for pb.Next() {
   212  				_ = p.Submit(task)
   213  			}
   214  		})
   215  	})
   216  
   217  	b.Run("CPUTask", func(b *testing.B) {
   218  		task, _ := newCPUTask()
   219  		b.RunParallel(func(pb *testing.PB) {
   220  			for pb.Next() {
   221  				_ = p.Submit(task)
   222  			}
   223  		})
   224  	})
   225  
   226  	b.Run("IOTask", func(b *testing.B) {
   227  		task, _ := newIOTask()
   228  		b.RunParallel(func(pb *testing.PB) {
   229  			for pb.Next() {
   230  				_ = p.Submit(task)
   231  			}
   232  		})
   233  	})
   234  
   235  	b.Run("RandomTask", func(b *testing.B) {
   236  		task, _ := newRandomTask()
   237  		b.RunParallel(func(pb *testing.PB) {
   238  			for pb.Next() {
   239  				_ = p.Submit(task)
   240  			}
   241  		})
   242  	})
   243  }