lessor_bench_test.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. // Copyright 2018 The etcd Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package lease
  15. import (
  16. "math/rand"
  17. "os"
  18. "testing"
  19. "time"
  20. "go.etcd.io/etcd/mvcc/backend"
  21. "go.uber.org/zap"
  22. )
  23. func BenchmarkLessorGrant1000(b *testing.B) { benchmarkLessorGrant(1000, b) }
  24. func BenchmarkLessorGrant100000(b *testing.B) { benchmarkLessorGrant(100000, b) }
  25. func BenchmarkLessorRevoke1000(b *testing.B) { benchmarkLessorRevoke(1000, b) }
  26. func BenchmarkLessorRevoke100000(b *testing.B) { benchmarkLessorRevoke(100000, b) }
  27. func BenchmarkLessorRenew1000(b *testing.B) { benchmarkLessorRenew(1000, b) }
  28. func BenchmarkLessorRenew100000(b *testing.B) { benchmarkLessorRenew(100000, b) }
  29. // Use findExpired10000 replace findExpired1000, which takes too long.
  30. func BenchmarkLessorFindExpired10000(b *testing.B) { benchmarkLessorFindExpired(10000, b) }
  31. func BenchmarkLessorFindExpired100000(b *testing.B) { benchmarkLessorFindExpired(100000, b) }
  32. func init() {
  33. rand.Seed(time.Now().UTC().UnixNano())
  34. }
  35. const (
  36. // minTTL keep lease will not auto expire in benchmark
  37. minTTL = 1000
  38. // maxTTL control repeat probability of ttls
  39. maxTTL = 2000
  40. )
  41. func randomTTL(n int, min, max int64) (out []int64) {
  42. for i := 0; i < n; i++ {
  43. out = append(out, rand.Int63n(max-min)+min)
  44. }
  45. return out
  46. }
  47. // demote lessor from being the primary, but don't change any lease's expiry
  48. func demote(le *lessor) {
  49. le.mu.Lock()
  50. defer le.mu.Unlock()
  51. close(le.demotec)
  52. le.demotec = nil
  53. }
  54. // return new lessor and tearDown to release resource
  55. func setUp() (le *lessor, tearDown func()) {
  56. lg := zap.NewNop()
  57. be, tmpPath := backend.NewDefaultTmpBackend()
  58. // MinLeaseTTL is negative, so we can grant expired lease in benchmark.
  59. // ExpiredLeasesRetryInterval should small, so benchmark of findExpired will recheck expired lease.
  60. le = newLessor(lg, be, LessorConfig{MinLeaseTTL: -1000, ExpiredLeasesRetryInterval: 10 * time.Microsecond})
  61. le.SetRangeDeleter(func() TxnDelete {
  62. ftd := &FakeTxnDelete{be.BatchTx()}
  63. ftd.Lock()
  64. return ftd
  65. })
  66. le.Promote(0)
  67. return le, func() {
  68. le.Stop()
  69. be.Close()
  70. os.Remove(tmpPath)
  71. }
  72. }
  73. func benchmarkLessorGrant(benchSize int, b *testing.B) {
  74. ttls := randomTTL(benchSize, minTTL, maxTTL)
  75. var le *lessor
  76. var tearDown func()
  77. b.ResetTimer()
  78. for i := 0; i < b.N; {
  79. b.StopTimer()
  80. if tearDown != nil {
  81. tearDown()
  82. tearDown = nil
  83. }
  84. le, tearDown = setUp()
  85. b.StartTimer()
  86. for j := 1; j <= benchSize; j++ {
  87. le.Grant(LeaseID(j), ttls[j-1])
  88. }
  89. i += benchSize
  90. }
  91. b.StopTimer()
  92. if tearDown != nil {
  93. tearDown()
  94. }
  95. }
  96. func benchmarkLessorRevoke(benchSize int, b *testing.B) {
  97. ttls := randomTTL(benchSize, minTTL, maxTTL)
  98. var le *lessor
  99. var tearDown func()
  100. b.ResetTimer()
  101. for i := 0; i < b.N; i++ {
  102. b.StopTimer()
  103. if tearDown != nil {
  104. tearDown()
  105. tearDown = nil
  106. }
  107. le, tearDown = setUp()
  108. for j := 1; j <= benchSize; j++ {
  109. le.Grant(LeaseID(j), ttls[j-1])
  110. }
  111. b.StartTimer()
  112. for j := 1; j <= benchSize; j++ {
  113. le.Revoke(LeaseID(j))
  114. }
  115. i += benchSize
  116. }
  117. b.StopTimer()
  118. if tearDown != nil {
  119. tearDown()
  120. }
  121. }
  122. func benchmarkLessorRenew(benchSize int, b *testing.B) {
  123. ttls := randomTTL(benchSize, minTTL, maxTTL)
  124. var le *lessor
  125. var tearDown func()
  126. b.ResetTimer()
  127. for i := 0; i < b.N; {
  128. b.StopTimer()
  129. if tearDown != nil {
  130. tearDown()
  131. tearDown = nil
  132. }
  133. le, tearDown = setUp()
  134. for j := 1; j <= benchSize; j++ {
  135. le.Grant(LeaseID(j), ttls[j-1])
  136. }
  137. b.StartTimer()
  138. for j := 1; j <= benchSize; j++ {
  139. le.Renew(LeaseID(j))
  140. }
  141. i += benchSize
  142. }
  143. b.StopTimer()
  144. if tearDown != nil {
  145. tearDown()
  146. }
  147. }
  148. func benchmarkLessorFindExpired(benchSize int, b *testing.B) {
  149. // 50% lease are expired.
  150. ttls := randomTTL(benchSize, -500, 500)
  151. findExpiredLimit := 50
  152. var le *lessor
  153. var tearDown func()
  154. b.ResetTimer()
  155. for i := 0; i < b.N; {
  156. b.StopTimer()
  157. if tearDown != nil {
  158. tearDown()
  159. tearDown = nil
  160. }
  161. le, tearDown = setUp()
  162. for j := 1; j <= benchSize; j++ {
  163. le.Grant(LeaseID(j), ttls[j-1])
  164. }
  165. // lessor's runLoop should not call findExpired
  166. demote(le)
  167. b.StartTimer()
  168. // refresh fixture after pop all expired lease
  169. for ; ; i++ {
  170. le.mu.Lock()
  171. ls := le.findExpiredLeases(findExpiredLimit)
  172. if len(ls) == 0 {
  173. break
  174. }
  175. le.mu.Unlock()
  176. // simulation: revoke lease after expired
  177. b.StopTimer()
  178. for _, lease := range ls {
  179. le.Revoke(lease.ID)
  180. }
  181. b.StartTimer()
  182. }
  183. }
  184. b.StopTimer()
  185. if tearDown != nil {
  186. tearDown()
  187. }
  188. }