github.com/q191201771/naza@v0.30.12/pkg/taskpool/taskpool_test.go (about)

     1  // Copyright 2019, Chef.  All rights reserved.
     2  // https://github.com/q191201771/naza
     3  //
     4  // Use of this source code is governed by a MIT-style license
     5  // that can be found in the License file.
     6  //
     7  // Author: Chef (191201771@qq.com)
     8  
     9  package taskpool_test
    10  
    11  import (
    12  	"github.com/q191201771/naza/pkg/nazaatomic"
    13  	"sync"
    14  	"sync/atomic"
    15  	"testing"
    16  	"time"
    17  
    18  	"github.com/q191201771/naza/pkg/taskpool"
    19  
    20  	"github.com/q191201771/naza/pkg/assert"
    21  	"github.com/q191201771/naza/pkg/nazalog"
    22  )
    23  
    24  var (
    25  	taskNum       = 1000 * 1000
    26  	initWorkerNum = 1 //1000 * 20 //1000 * 10
    27  )
    28  
    29  func BenchmarkOriginGo(b *testing.B) {
    30  	nazalog.Debug("> BenchmarkOriginGo")
    31  	var wg sync.WaitGroup
    32  	for j := 0; j < 1; j++ {
    33  		wg.Add(taskNum)
    34  		for i := 0; i < taskNum; i++ {
    35  			go func() {
    36  				time.Sleep(10 * time.Millisecond)
    37  				wg.Done()
    38  			}()
    39  		}
    40  		wg.Wait()
    41  	}
    42  	nazalog.Debug("< BenchmarkOriginGo")
    43  }
    44  
    45  func BenchmarkTaskPool(b *testing.B) {
    46  	nazalog.Debug("> BenchmarkTaskPool")
    47  	var wg sync.WaitGroup
    48  	p, _ := taskpool.NewPool(func(option *taskpool.Option) {
    49  		option.InitWorkerNum = initWorkerNum
    50  	})
    51  
    52  	b.ResetTimer()
    53  	for j := 0; j < 1; j++ {
    54  		//b.StartTimer()
    55  		wg.Add(taskNum)
    56  		for i := 0; i < taskNum; i++ {
    57  			p.Go(func(param ...interface{}) {
    58  				time.Sleep(10 * time.Millisecond)
    59  				wg.Done()
    60  			})
    61  		}
    62  		wg.Wait()
    63  	}
    64  	nazalog.Debug("< BenchmarkTaskPool")
    65  }
    66  
    67  func TestTaskPool(t *testing.T) {
    68  	var wg sync.WaitGroup
    69  	p, _ := taskpool.NewPool(func(option *taskpool.Option) {
    70  		option.InitWorkerNum = 1
    71  	})
    72  
    73  	go func() {
    74  		//for {
    75  		nazalog.Debugf("timer, worker num. status=%+v", p.GetCurrentStatus())
    76  		time.Sleep(10 * time.Millisecond)
    77  		//}
    78  	}()
    79  
    80  	n := 1000
    81  	wg.Add(n)
    82  	nazalog.Debug("start.")
    83  	for i := 0; i < n; i++ {
    84  		p.Go(func(param ...interface{}) {
    85  			time.Sleep(10 * time.Millisecond)
    86  			wg.Done()
    87  		})
    88  	}
    89  	wg.Wait()
    90  	nazalog.Debugf("done, worker num. status=%+v", p.GetCurrentStatus()) // 此时还有个别busy也是正常的,因为只是业务方的任务代码执行完了,可能还没回收到idle队列中
    91  	p.KillIdleWorkers()
    92  	nazalog.Debugf("killed, worker num. status=%+v", p.GetCurrentStatus())
    93  
    94  	time.Sleep(100 * time.Millisecond)
    95  
    96  	wg.Add(n)
    97  	for i := 0; i < n; i++ {
    98  		p.Go(func(param ...interface{}) {
    99  			time.Sleep(10 * time.Millisecond)
   100  			wg.Done()
   101  		})
   102  	}
   103  	wg.Wait()
   104  	nazalog.Debugf("done, worker num. status=%+v", p.GetCurrentStatus())
   105  }
   106  
   107  func TestMaxWorker(t *testing.T) {
   108  	p, err := taskpool.NewPool(func(option *taskpool.Option) {
   109  		option.MaxWorkerNum = 128
   110  	})
   111  	assert.Equal(t, nil, err)
   112  
   113  	go func() {
   114  		for i := 0; i < 5; i++ {
   115  			nazalog.Debugf("timer. status=%+v", p.GetCurrentStatus())
   116  			time.Sleep(100 * time.Millisecond)
   117  		}
   118  	}()
   119  
   120  	var wg sync.WaitGroup
   121  	var sum int32
   122  	n := 1000
   123  	wg.Add(n)
   124  	nazalog.Debugf("start.")
   125  	for i := 0; i < n; i++ {
   126  		p.Go(func(param ...interface{}) {
   127  			a := param[0].(int)
   128  			b := param[1].(int)
   129  			atomic.AddInt32(&sum, int32(a))
   130  			atomic.AddInt32(&sum, int32(b))
   131  			time.Sleep(10 * time.Millisecond)
   132  			wg.Done()
   133  		}, i, i)
   134  	}
   135  	wg.Wait()
   136  	nazalog.Debugf("end. sum=%d", sum)
   137  }
   138  
   139  func TestGlobal(t *testing.T) {
   140  	err := taskpool.Init()
   141  	assert.Equal(t, nil, err)
   142  	s := taskpool.GetCurrentStatus()
   143  	assert.Equal(t, 0, s.TotalWorkerNum)
   144  	assert.Equal(t, 0, s.IdleWorkerNum)
   145  	assert.Equal(t, 0, s.BlockTaskNum)
   146  	taskpool.Go(func(param ...interface{}) {
   147  	})
   148  	taskpool.KillIdleWorkers()
   149  }
   150  
   151  func TestCorner(t *testing.T) {
   152  	_, err := taskpool.NewPool(func(option *taskpool.Option) {
   153  		option.InitWorkerNum = -1
   154  	})
   155  	assert.Equal(t, taskpool.ErrTaskPool, err)
   156  
   157  	_, err = taskpool.NewPool(func(option *taskpool.Option) {
   158  		option.MaxWorkerNum = -1
   159  	})
   160  	assert.Equal(t, taskpool.ErrTaskPool, err)
   161  
   162  	_, err = taskpool.NewPool(func(option *taskpool.Option) {
   163  		option.InitWorkerNum = 5
   164  		option.MaxWorkerNum = 1
   165  	})
   166  	assert.Equal(t, taskpool.ErrTaskPool, err)
   167  }
   168  
   169  func TestPool_Dispose2(t *testing.T) {
   170  	// 测试 DisposeTypeRunAllBlockTask
   171  
   172  	tp, _ := taskpool.NewPool(func(option *taskpool.Option) {
   173  		option.InitWorkerNum = 2
   174  		option.MaxWorkerNum = 2
   175  	})
   176  
   177  	var count nazaatomic.Int32
   178  	for i := 0; i < 10; i++ {
   179  		tp.Go(func(param ...interface{}) {
   180  			ii := param[0].(int)
   181  			time.Sleep(time.Duration(10) * time.Millisecond)
   182  			nazalog.Debugf("%d", ii)
   183  			count.Increment()
   184  		}, i)
   185  	}
   186  
   187  	nazalog.Debugf("%+v", tp.GetCurrentStatus())
   188  	tp.Dispose(taskpool.DisposeTypeRunAllBlockTask)
   189  	nazalog.Debugf("%+v", tp.GetCurrentStatus())
   190  	time.Sleep(200 * time.Millisecond)
   191  	assert.Equal(t, 10, int(count.Load()))
   192  	nazalog.Debugf("%+v", tp.GetCurrentStatus())
   193  
   194  	// 测试空闲情况dispose
   195  	{
   196  		tpp, _ := taskpool.NewPool(func(option *taskpool.Option) {
   197  			option.InitWorkerNum = 2
   198  		})
   199  		nazalog.Debugf("%+v", tp.GetCurrentStatus())
   200  		tpp.Dispose(taskpool.DisposeTypeAsap)
   201  		nazalog.Debugf("%+v", tp.GetCurrentStatus())
   202  	}
   203  }
   204  
   205  func TestPool_Dispose(t *testing.T) {
   206  	tp, _ := taskpool.NewPool(func(option *taskpool.Option) {
   207  		option.InitWorkerNum = 1
   208  		option.MaxWorkerNum = 1
   209  	})
   210  
   211  	var v nazaatomic.Int32
   212  
   213  	// 任务1在dispose之前已经被执行的任务,但是由于自身的sleep导致没有执行完,从而导致任务2,3在dispose时处于阻塞状态,还没有被执行
   214  	// 也因此,任务2,,3在dispose后不再执行
   215  	tp.Go(func(param ...interface{}) {
   216  		nazalog.Debugf("> task 1")
   217  		time.Sleep(100 * time.Millisecond)
   218  		nazalog.Debugf("< task 1")
   219  		v.Add(1)
   220  	})
   221  
   222  	tp.Go(func(param ...interface{}) {
   223  		nazalog.Debugf("> task 2")
   224  		time.Sleep(300 * time.Millisecond)
   225  		nazalog.Debugf("< task 2")
   226  		v.Add(2)
   227  	})
   228  
   229  	tp.Go(func(param ...interface{}) {
   230  		nazalog.Debugf("> task 3")
   231  		time.Sleep(500 * time.Millisecond)
   232  		nazalog.Debugf("< task 3")
   233  		v.Add(4)
   234  	})
   235  
   236  	nazalog.Debugf("%+v", tp.GetCurrentStatus())
   237  	time.Sleep(50 * time.Millisecond)
   238  	nazalog.Debugf("%+v", tp.GetCurrentStatus())
   239  	tp.Dispose(taskpool.DisposeTypeAsap)
   240  
   241  	nazalog.Debugf("%+v", tp.GetCurrentStatus())
   242  	time.Sleep(400 * time.Millisecond)
   243  
   244  	tp.Dispose(taskpool.DisposeTypeAsap)
   245  	tp.Go(func(param ...interface{}) {
   246  	})
   247  	tp.KillIdleWorkers()
   248  	nazalog.Debugf("%+v", tp.GetCurrentStatus())
   249  
   250  	assert.Equal(t, 1, int(v.Load()))
   251  }