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 }