github.com/benz9527/xboot@v0.0.0-20240504061247-c23f15593274/lib/queue/delay_queue_linux_test.go (about)

     1  //go:build linux
     2  // +build linux
     3  
     4  package queue
     5  
     6  import (
     7  	"context"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/stretchr/testify/assert"
    12  
    13  	"github.com/benz9527/xboot/lib/hrtime"
    14  	"github.com/benz9527/xboot/lib/infra"
    15  )
    16  
    17  func TestArrayDelayQueue_PollToChan_unix(t *testing.T) {
    18  	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
    19  	defer cancel()
    20  
    21  	dq := NewArrayDelayQueue[*employee](ctx, 32)
    22  	receiver := infra.NewSafeClosableChannel[*employee]()
    23  	go dq.PollToChan(
    24  		func() int64 {
    25  			return hrtime.UnixMonotonicClock.NowInDefaultTZ().UnixMilli()
    26  		},
    27  		receiver,
    28  	)
    29  
    30  	ms := hrtime.UnixMonotonicClock.NowInDefaultTZ().UnixMilli()
    31  	dq.Offer(&employee{age: 10, name: "p0", salary: ms + 110}, ms+110)
    32  	dq.Offer(&employee{age: 101, name: "p1", salary: ms + 501}, ms+501)
    33  	dq.Offer(&employee{age: 10, name: "p2", salary: ms + 155}, ms+155)
    34  	dq.Offer(&employee{age: 200, name: "p3", salary: ms + 210}, ms+210)
    35  	dq.Offer(&employee{age: 3, name: "p4", salary: ms + 60}, ms+60)
    36  	dq.Offer(&employee{age: 1, name: "p5", salary: ms + 110}, ms+110)
    37  	dq.Offer(&employee{age: 5, name: "p6", salary: ms + 250}, ms+250)
    38  	dq.Offer(&employee{age: 200, name: "p7", salary: ms + 301}, ms+301)
    39  
    40  	expectedCount := 8
    41  	actualCount := 0
    42  	defer func() {
    43  		assert.LessOrEqual(t, actualCount, expectedCount)
    44  	}()
    45  
    46  	time.AfterFunc(300*time.Millisecond, func() {
    47  		_ = receiver.Close()
    48  	})
    49  	itemC := receiver.Wait()
    50  	for {
    51  		select {
    52  		default:
    53  			if receiver.IsClosed() {
    54  				return
    55  			}
    56  		case item, ok := <-itemC:
    57  			if !ok {
    58  				t.Log("receiver channel closed")
    59  				time.Sleep(100 * time.Millisecond)
    60  				return
    61  			}
    62  			now := hrtime.UnixMonotonicClock.NowInDefaultTZ().UnixMilli()
    63  			t.Logf("current time ms: %d, item: %v, diff: %d\n", now, item, now-item.salary)
    64  			actualCount++
    65  		}
    66  	}
    67  }
    68  
    69  func BenchmarkDelayQueue_PollToChan_hrtime_unix(b *testing.B) {
    70  
    71  	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(b.N+10)*time.Millisecond)
    72  	defer cancel()
    73  
    74  	dq := NewArrayDelayQueue[*employee](ctx, 32)
    75  
    76  	receiver := infra.NewSafeClosableChannel[*employee]()
    77  	go dq.PollToChan(
    78  		func() int64 {
    79  			return hrtime.UnixMonotonicClock.NowInDefaultTZ().UnixMilli()
    80  		},
    81  		receiver,
    82  	)
    83  	go func(ctx context.Context) {
    84  		<-ctx.Done()
    85  		_ = receiver.Close()
    86  	}(ctx)
    87  	ms := hrtime.UnixMonotonicClock.NowInDefaultTZ().UnixMilli()
    88  	b.ResetTimer()
    89  	for i := 0; i < b.N; i++ {
    90  		dq.Offer(&employee{age: i, name: "p", salary: int64(i)}, ms+int64(i))
    91  	}
    92  
    93  	defer func() {
    94  		b.StopTimer()
    95  		b.ReportAllocs()
    96  	}()
    97  	itemC := receiver.Wait()
    98  	for {
    99  		select {
   100  		default:
   101  			if receiver.IsClosed() {
   102  				return
   103  			}
   104  		case <-itemC:
   105  
   106  		}
   107  	}
   108  }
   109  
   110  func BenchmarkDelayQueue_PollToChan_hrtime_gonative(b *testing.B) {
   111  
   112  	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(b.N+10)*time.Millisecond)
   113  	defer cancel()
   114  
   115  	dq := NewArrayDelayQueue[*employee](ctx, 32)
   116  
   117  	receiver := infra.NewSafeClosableChannel[*employee]()
   118  	go dq.PollToChan(
   119  		func() int64 {
   120  			return hrtime.GoMonotonicClock.NowInDefaultTZ().UnixMilli()
   121  		},
   122  		receiver,
   123  	)
   124  	go func(ctx context.Context) {
   125  		<-ctx.Done()
   126  		_ = receiver.Close()
   127  	}(ctx)
   128  	ms := hrtime.GoMonotonicClock.NowInDefaultTZ().UnixMilli()
   129  	b.ResetTimer()
   130  	for i := 0; i < b.N; i++ {
   131  		dq.Offer(&employee{age: i, name: "p", salary: int64(i)}, ms+int64(i))
   132  	}
   133  
   134  	defer func() {
   135  		b.StopTimer()
   136  		b.ReportAllocs()
   137  	}()
   138  	itemC := receiver.Wait()
   139  	for {
   140  		select {
   141  		default:
   142  			if receiver.IsClosed() {
   143  				return
   144  			}
   145  		case <-itemC:
   146  
   147  		}
   148  	}
   149  }