-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathqueue_bench_test.go
More file actions
123 lines (107 loc) · 3.78 KB
/
queue_bench_test.go
File metadata and controls
123 lines (107 loc) · 3.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package rate_envelope_queue
import (
"context"
"testing"
"time"
)
// go test -bench=BenchmarkQueueFull -benchmem
func BenchmarkQueueFull(b *testing.B) {
q := NewRateEnvelopeQueue(context.Background(), "bench",
WithLimitOption(64), // количество воркеров
WithStopModeOption(Drain), // корректный останов
WithAllowedCapacityOption(9_000_000), // высокая ёмкость
)
q.Start()
defer q.Stop()
// пустые хуки
before := func(ctx context.Context, e *Envelope) error { return nil }
invoke := func(ctx context.Context, e *Envelope) error { return nil }
after := func(ctx context.Context, e *Envelope) error { return nil }
failure := func(ctx context.Context, e *Envelope, err error) Decision {
return DefaultOnceDecision()
}
success := func(ctx context.Context, e *Envelope) {}
env, _ := NewEnvelope(
WithId(1),
WithType("bench"),
WithBeforeHook(before),
WithInvoke(invoke),
WithAfterHook(after),
WithFailureHook(failure),
WithSuccessHook(success),
WithDeadline(50*time.Millisecond),
)
// сбрасываем таймер, чтобы не учитывать сетап
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := q.Send(env); err != nil {
b.Fatal(err)
}
}
}
// go test -bench=BenchmarkQueueInterval -benchmem
func BenchmarkQueueInterval(b *testing.B) {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
q := NewRateEnvelopeQueue(ctx, "bench-interval",
WithLimitOption(64), // воркеры
WithStopModeOption(Drain), // аккуратный останов
WithAllowedCapacityOption(1_000_000), // большой запас
)
q.Start()
defer q.Stop()
before := func(ctx context.Context, e *Envelope) error { return nil }
invoke := func(ctx context.Context, e *Envelope) error { return nil }
after := func(ctx context.Context, e *Envelope) error { return nil }
failure := func(ctx context.Context, e *Envelope, err error) Decision {
return DefaultOnceDecision()
}
success := func(ctx context.Context, e *Envelope) {}
// периодическая задача с небольшим интервалом
env, _ := NewEnvelope(
WithId(1),
WithType("interval"),
WithBeforeHook(before),
WithInvoke(invoke),
WithAfterHook(after),
WithFailureHook(failure),
WithSuccessHook(success),
WithScheduleModeInterval(30*time.Millisecond), // каждые 30мс
WithDeadline(20*time.Millisecond),
)
// загружаем одну задачу для перепланировки
if err := q.Send(env); err != nil {
b.Fatal(err)
}
// сбрасываем таймер, чтобы не учитывать сетап
b.ResetTimer()
// прогоняем b.N итераций, чтобы нагрузить планировщик AddAfter
for i := 0; i < b.N; i++ {
// динамически создаём ещё один Envelope, чтобы система обрабатывала их параллельно
e, _ := NewEnvelope(
WithId(uint64(i+2)),
WithType("dyn"),
WithBeforeHook(before),
WithInvoke(invoke),
WithAfterHook(after),
WithFailureHook(failure),
WithSuccessHook(success),
WithScheduleModeInterval(time.Millisecond*11), // короче интервал
WithDeadline(time.Millisecond*10),
)
if err := q.Send(e); err != nil {
b.Fatal(err)
}
}
}
/*
Benchmark results (user-reported)
$ go test -bench=BenchmarkQueueFull -benchmem
3212882 348.7 ns/op 40 B/op 1 allocs/op
PASS
ok github.com/PavelAgarkov/rate-envelope-queue 1.507s
$ go test -bench=BenchmarkQueueInterval -benchmem
91557 14199 ns/op 1922 B/op 25 allocs/op
PASS
ok github.com/PavelAgarkov/rate-envelope-queue 1.441s
*/