| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 |
- package nebula
- import (
- "testing"
- "time"
- )
- func TestScheduler_PooledReuse(t *testing.T) {
- ctx := t.Context()
- s := NewScheduler[int](16)
- delivered := make(chan int, 256)
- go s.Run(ctx, func(item int) { delivered <- item })
- const N = 100
- for i := range N {
- s.Schedule(ctx, i, time.Millisecond)
- }
- deadline := time.After(2 * time.Second)
- got := 0
- for got < N {
- select {
- case <-delivered:
- got++
- case <-deadline:
- t.Fatalf("only %d/%d items delivered", got, N)
- }
- }
- }
- // BenchmarkScheduler_Schedule reports allocations per Schedule call.
- // In steady state the Scheduler's sync.Pool means we should see zero allocs per op once the pool warms up.
- func BenchmarkScheduler_Schedule(b *testing.B) {
- ctx := b.Context()
- s := NewScheduler[int](b.N)
- go s.Run(ctx, func(int) {})
- b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- s.Schedule(ctx, i, time.Microsecond)
- }
- }
- // BenchmarkBareAfterFunc is the comparison baseline.
- // What we'd pay per Schedule if Punchy called time.AfterFunc directly without the pooled Scheduler.
- // Allocates a *time.Timer plus a closure each call.
- func BenchmarkBareAfterFunc(b *testing.B) {
- ctx := b.Context()
- queue := make(chan int, b.N)
- go func() {
- for {
- select {
- case <-ctx.Done():
- return
- case <-queue:
- }
- }
- }()
- b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- i := i
- time.AfterFunc(time.Microsecond, func() {
- select {
- case queue <- i:
- case <-ctx.Done():
- }
- })
- }
- }
|