mirror of
https://github.com/restic/restic.git
synced 2024-08-21 11:53:22 +02:00
132 lines
2.8 KiB
Go
132 lines
2.8 KiB
Go
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style
|
||
|
// license that can be found in the LICENSE file.
|
||
|
|
||
|
// +build go1.7
|
||
|
|
||
|
package semaphore_test
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"testing"
|
||
|
|
||
|
"golang.org/x/net/context"
|
||
|
"golang.org/x/sync/semaphore"
|
||
|
)
|
||
|
|
||
|
// weighted is an interface matching a subset of *Weighted. It allows
|
||
|
// alternate implementations for testing and benchmarking.
|
||
|
type weighted interface {
|
||
|
Acquire(context.Context, int64) error
|
||
|
TryAcquire(int64) bool
|
||
|
Release(int64)
|
||
|
}
|
||
|
|
||
|
// semChan implements Weighted using a channel for
|
||
|
// comparing against the condition variable-based implementation.
|
||
|
type semChan chan struct{}
|
||
|
|
||
|
func newSemChan(n int64) semChan {
|
||
|
return semChan(make(chan struct{}, n))
|
||
|
}
|
||
|
|
||
|
func (s semChan) Acquire(_ context.Context, n int64) error {
|
||
|
for i := int64(0); i < n; i++ {
|
||
|
s <- struct{}{}
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (s semChan) TryAcquire(n int64) bool {
|
||
|
if int64(len(s))+n > int64(cap(s)) {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
for i := int64(0); i < n; i++ {
|
||
|
s <- struct{}{}
|
||
|
}
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
func (s semChan) Release(n int64) {
|
||
|
for i := int64(0); i < n; i++ {
|
||
|
<-s
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// acquireN calls Acquire(size) on sem N times and then calls Release(size) N times.
|
||
|
func acquireN(b *testing.B, sem weighted, size int64, N int) {
|
||
|
b.ResetTimer()
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
for j := 0; j < N; j++ {
|
||
|
sem.Acquire(context.Background(), size)
|
||
|
}
|
||
|
for j := 0; j < N; j++ {
|
||
|
sem.Release(size)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// tryAcquireN calls TryAcquire(size) on sem N times and then calls Release(size) N times.
|
||
|
func tryAcquireN(b *testing.B, sem weighted, size int64, N int) {
|
||
|
b.ResetTimer()
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
for j := 0; j < N; j++ {
|
||
|
if !sem.TryAcquire(size) {
|
||
|
b.Fatalf("TryAcquire(%v) = false, want true", size)
|
||
|
}
|
||
|
}
|
||
|
for j := 0; j < N; j++ {
|
||
|
sem.Release(size)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkNewSeq(b *testing.B) {
|
||
|
for _, cap := range []int64{1, 128} {
|
||
|
b.Run(fmt.Sprintf("Weighted-%d", cap), func(b *testing.B) {
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
_ = semaphore.NewWeighted(cap)
|
||
|
}
|
||
|
})
|
||
|
b.Run(fmt.Sprintf("semChan-%d", cap), func(b *testing.B) {
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
_ = newSemChan(cap)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkAcquireSeq(b *testing.B) {
|
||
|
for _, c := range []struct {
|
||
|
cap, size int64
|
||
|
N int
|
||
|
}{
|
||
|
{1, 1, 1},
|
||
|
{2, 1, 1},
|
||
|
{16, 1, 1},
|
||
|
{128, 1, 1},
|
||
|
{2, 2, 1},
|
||
|
{16, 2, 8},
|
||
|
{128, 2, 64},
|
||
|
{2, 1, 2},
|
||
|
{16, 8, 2},
|
||
|
{128, 64, 2},
|
||
|
} {
|
||
|
for _, w := range []struct {
|
||
|
name string
|
||
|
w weighted
|
||
|
}{
|
||
|
{"Weighted", semaphore.NewWeighted(c.cap)},
|
||
|
{"semChan", newSemChan(c.cap)},
|
||
|
} {
|
||
|
b.Run(fmt.Sprintf("%s-acquire-%d-%d-%d", w.name, c.cap, c.size, c.N), func(b *testing.B) {
|
||
|
acquireN(b, w.w, c.size, c.N)
|
||
|
})
|
||
|
b.Run(fmt.Sprintf("%s-tryAcquire-%d-%d-%d", w.name, c.cap, c.size, c.N), func(b *testing.B) {
|
||
|
tryAcquireN(b, w.w, c.size, c.N)
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
}
|