1
2
3
4
5
6
7
8 package semaphore_test
9
10 import (
11 "context"
12 "fmt"
13 "testing"
14
15 "github.com/letsencrypt/boulder/semaphore"
16 )
17
18
19
20 type weighted interface {
21 Acquire(context.Context, int64) error
22 TryAcquire(int64) bool
23 Release(int64)
24 }
25
26
27
28 type semChan chan struct{}
29
30 func newSemChan(n int64) semChan {
31 return semChan(make(chan struct{}, n))
32 }
33
34 func (s semChan) Acquire(_ context.Context, n int64) error {
35 for i := int64(0); i < n; i++ {
36 s <- struct{}{}
37 }
38 return nil
39 }
40
41 func (s semChan) TryAcquire(n int64) bool {
42 if int64(len(s))+n > int64(cap(s)) {
43 return false
44 }
45
46 for i := int64(0); i < n; i++ {
47 s <- struct{}{}
48 }
49 return true
50 }
51
52 func (s semChan) Release(n int64) {
53 for i := int64(0); i < n; i++ {
54 <-s
55 }
56 }
57
58
59 func acquireN(b *testing.B, sem weighted, size int64, N int) {
60 b.ResetTimer()
61 for i := 0; i < b.N; i++ {
62 for j := 0; j < N; j++ {
63 _ = sem.Acquire(context.Background(), size)
64 }
65 for j := 0; j < N; j++ {
66 sem.Release(size)
67 }
68 }
69 }
70
71
72 func tryAcquireN(b *testing.B, sem weighted, size int64, N int) {
73 b.ResetTimer()
74 for i := 0; i < b.N; i++ {
75 for j := 0; j < N; j++ {
76 if !sem.TryAcquire(size) {
77 b.Fatalf("TryAcquire(%v) = false, want true", size)
78 }
79 }
80 for j := 0; j < N; j++ {
81 sem.Release(size)
82 }
83 }
84 }
85
86 func BenchmarkNewSeq(b *testing.B) {
87 for _, cap := range []int64{1, 128} {
88 b.Run(fmt.Sprintf("Weighted-%d", cap), func(b *testing.B) {
89 for i := 0; i < b.N; i++ {
90 _ = semaphore.NewWeighted(cap, 0)
91 }
92 })
93 b.Run(fmt.Sprintf("semChan-%d", cap), func(b *testing.B) {
94 for i := 0; i < b.N; i++ {
95 _ = newSemChan(cap)
96 }
97 })
98 }
99 }
100
101 func BenchmarkAcquireSeq(b *testing.B) {
102 for _, c := range []struct {
103 cap, size int64
104 N int
105 }{
106 {1, 1, 1},
107 {2, 1, 1},
108 {16, 1, 1},
109 {128, 1, 1},
110 {2, 2, 1},
111 {16, 2, 8},
112 {128, 2, 64},
113 {2, 1, 2},
114 {16, 8, 2},
115 {128, 64, 2},
116 } {
117 for _, w := range []struct {
118 name string
119 w weighted
120 }{
121 {"Weighted", semaphore.NewWeighted(c.cap, 0)},
122 {"semChan", newSemChan(c.cap)},
123 } {
124 b.Run(fmt.Sprintf("%s-acquire-%d-%d-%d", w.name, c.cap, c.size, c.N), func(b *testing.B) {
125 acquireN(b, w.w, c.size, c.N)
126 })
127 b.Run(fmt.Sprintf("%s-tryAcquire-%d-%d-%d", w.name, c.cap, c.size, c.N), func(b *testing.B) {
128 tryAcquireN(b, w.w, c.size, c.N)
129 })
130 }
131 }
132 }
133
View as plain text