Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 

132 lignes
2.8 KiB

  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.
  4. // +build go1.7
  5. package semaphore_test
  6. import (
  7. "context"
  8. "fmt"
  9. "testing"
  10. "golang.org/x/sync/semaphore"
  11. )
  12. // weighted is an interface matching a subset of *Weighted. It allows
  13. // alternate implementations for testing and benchmarking.
  14. type weighted interface {
  15. Acquire(context.Context, int64) error
  16. TryAcquire(int64) bool
  17. Release(int64)
  18. }
  19. // semChan implements Weighted using a channel for
  20. // comparing against the condition variable-based implementation.
  21. type semChan chan struct{}
  22. func newSemChan(n int64) semChan {
  23. return semChan(make(chan struct{}, n))
  24. }
  25. func (s semChan) Acquire(_ context.Context, n int64) error {
  26. for i := int64(0); i < n; i++ {
  27. s <- struct{}{}
  28. }
  29. return nil
  30. }
  31. func (s semChan) TryAcquire(n int64) bool {
  32. if int64(len(s))+n > int64(cap(s)) {
  33. return false
  34. }
  35. for i := int64(0); i < n; i++ {
  36. s <- struct{}{}
  37. }
  38. return true
  39. }
  40. func (s semChan) Release(n int64) {
  41. for i := int64(0); i < n; i++ {
  42. <-s
  43. }
  44. }
  45. // acquireN calls Acquire(size) on sem N times and then calls Release(size) N times.
  46. func acquireN(b *testing.B, sem weighted, size int64, N int) {
  47. b.ResetTimer()
  48. for i := 0; i < b.N; i++ {
  49. for j := 0; j < N; j++ {
  50. sem.Acquire(context.Background(), size)
  51. }
  52. for j := 0; j < N; j++ {
  53. sem.Release(size)
  54. }
  55. }
  56. }
  57. // tryAcquireN calls TryAcquire(size) on sem N times and then calls Release(size) N times.
  58. func tryAcquireN(b *testing.B, sem weighted, size int64, N int) {
  59. b.ResetTimer()
  60. for i := 0; i < b.N; i++ {
  61. for j := 0; j < N; j++ {
  62. if !sem.TryAcquire(size) {
  63. b.Fatalf("TryAcquire(%v) = false, want true", size)
  64. }
  65. }
  66. for j := 0; j < N; j++ {
  67. sem.Release(size)
  68. }
  69. }
  70. }
  71. func BenchmarkNewSeq(b *testing.B) {
  72. for _, cap := range []int64{1, 128} {
  73. b.Run(fmt.Sprintf("Weighted-%d", cap), func(b *testing.B) {
  74. for i := 0; i < b.N; i++ {
  75. _ = semaphore.NewWeighted(cap)
  76. }
  77. })
  78. b.Run(fmt.Sprintf("semChan-%d", cap), func(b *testing.B) {
  79. for i := 0; i < b.N; i++ {
  80. _ = newSemChan(cap)
  81. }
  82. })
  83. }
  84. }
  85. func BenchmarkAcquireSeq(b *testing.B) {
  86. for _, c := range []struct {
  87. cap, size int64
  88. N int
  89. }{
  90. {1, 1, 1},
  91. {2, 1, 1},
  92. {16, 1, 1},
  93. {128, 1, 1},
  94. {2, 2, 1},
  95. {16, 2, 8},
  96. {128, 2, 64},
  97. {2, 1, 2},
  98. {16, 8, 2},
  99. {128, 64, 2},
  100. } {
  101. for _, w := range []struct {
  102. name string
  103. w weighted
  104. }{
  105. {"Weighted", semaphore.NewWeighted(c.cap)},
  106. {"semChan", newSemChan(c.cap)},
  107. } {
  108. b.Run(fmt.Sprintf("%s-acquire-%d-%d-%d", w.name, c.cap, c.size, c.N), func(b *testing.B) {
  109. acquireN(b, w.w, c.size, c.N)
  110. })
  111. b.Run(fmt.Sprintf("%s-tryAcquire-%d-%d-%d", w.name, c.cap, c.size, c.N), func(b *testing.B) {
  112. tryAcquireN(b, w.w, c.size, c.N)
  113. })
  114. }
  115. }
  116. }