1 // Copyright 2017 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
14 "golang.org/x/sync/semaphore"
17 // weighted is an interface matching a subset of *Weighted. It allows
18 // alternate implementations for testing and benchmarking.
19 type weighted interface {
20 Acquire(context.Context, int64) error
21 TryAcquire(int64) bool
25 // semChan implements Weighted using a channel for
26 // comparing against the condition variable-based implementation.
27 type semChan chan struct{}
29 func newSemChan(n int64) semChan {
30 return semChan(make(chan struct{}, n))
33 func (s semChan) Acquire(_ context.Context, n int64) error {
34 for i := int64(0); i < n; i++ {
40 func (s semChan) TryAcquire(n int64) bool {
41 if int64(len(s))+n > int64(cap(s)) {
45 for i := int64(0); i < n; i++ {
51 func (s semChan) Release(n int64) {
52 for i := int64(0); i < n; i++ {
57 // acquireN calls Acquire(size) on sem N times and then calls Release(size) N times.
58 func acquireN(b *testing.B, sem weighted, size int64, N int) {
60 for i := 0; i < b.N; i++ {
61 for j := 0; j < N; j++ {
62 sem.Acquire(context.Background(), size)
64 for j := 0; j < N; j++ {
70 // tryAcquireN calls TryAcquire(size) on sem N times and then calls Release(size) N times.
71 func tryAcquireN(b *testing.B, sem weighted, size int64, N int) {
73 for i := 0; i < b.N; i++ {
74 for j := 0; j < N; j++ {
75 if !sem.TryAcquire(size) {
76 b.Fatalf("TryAcquire(%v) = false, want true", size)
79 for j := 0; j < N; j++ {
85 func BenchmarkNewSeq(b *testing.B) {
86 for _, cap := range []int64{1, 128} {
87 b.Run(fmt.Sprintf("Weighted-%d", cap), func(b *testing.B) {
88 for i := 0; i < b.N; i++ {
89 _ = semaphore.NewWeighted(cap)
92 b.Run(fmt.Sprintf("semChan-%d", cap), func(b *testing.B) {
93 for i := 0; i < b.N; i++ {
100 func BenchmarkAcquireSeq(b *testing.B) {
101 for _, c := range []struct {
116 for _, w := range []struct {
120 {"Weighted", semaphore.NewWeighted(c.cap)},
121 {"semChan", newSemChan(c.cap)},
123 b.Run(fmt.Sprintf("%s-acquire-%d-%d-%d", w.name, c.cap, c.size, c.N), func(b *testing.B) {
124 acquireN(b, w.w, c.size, c.N)
126 b.Run(fmt.Sprintf("%s-tryAcquire-%d-%d-%d", w.name, c.cap, c.size, c.N), func(b *testing.B) {
127 tryAcquireN(b, w.w, c.size, c.N)