...

Source file src/go.etcd.io/etcd/server/v3/lease/lessor_bench_test.go

Documentation: go.etcd.io/etcd/server/v3/lease

     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  
    15  package lease
    16  
    17  import (
    18  	"math/rand"
    19  	"testing"
    20  	"time"
    21  
    22  	betesting "go.etcd.io/etcd/server/v3/mvcc/backend/testing"
    23  	"go.uber.org/zap"
    24  )
    25  
    26  func BenchmarkLessorGrant1000(b *testing.B)   { benchmarkLessorGrant(1000, b) }
    27  func BenchmarkLessorGrant100000(b *testing.B) { benchmarkLessorGrant(100000, b) }
    28  
    29  func BenchmarkLessorRevoke1000(b *testing.B)   { benchmarkLessorRevoke(1000, b) }
    30  func BenchmarkLessorRevoke100000(b *testing.B) { benchmarkLessorRevoke(100000, b) }
    31  
    32  func BenchmarkLessorRenew1000(b *testing.B)   { benchmarkLessorRenew(1000, b) }
    33  func BenchmarkLessorRenew100000(b *testing.B) { benchmarkLessorRenew(100000, b) }
    34  
    35  // BenchmarkLessorFindExpired10000 use findExpired10000 replace findExpired1000, which takes too long.
    36  func BenchmarkLessorFindExpired10000(b *testing.B)  { benchmarkLessorFindExpired(10000, b) }
    37  func BenchmarkLessorFindExpired100000(b *testing.B) { benchmarkLessorFindExpired(100000, b) }
    38  
    39  func init() {
    40  	rand.Seed(time.Now().UTC().UnixNano())
    41  }
    42  
    43  const (
    44  	// minTTL keep lease will not auto expire in benchmark
    45  	minTTL = 1000
    46  	// maxTTL control repeat probability of ttls
    47  	maxTTL = 2000
    48  )
    49  
    50  func randomTTL(n int, min, max int64) (out []int64) {
    51  	for i := 0; i < n; i++ {
    52  		out = append(out, rand.Int63n(max-min)+min)
    53  	}
    54  	return out
    55  }
    56  
    57  // demote lessor from being the primary, but don't change any lease's expiry
    58  func demote(le *lessor) {
    59  	le.mu.Lock()
    60  	defer le.mu.Unlock()
    61  	close(le.demotec)
    62  	le.demotec = nil
    63  }
    64  
    65  // return new lessor and tearDown to release resource
    66  func setUp(t testing.TB) (le *lessor, tearDown func()) {
    67  	lg := zap.NewNop()
    68  	be, _ := betesting.NewDefaultTmpBackend(t)
    69  	// MinLeaseTTL is negative, so we can grant expired lease in benchmark.
    70  	// ExpiredLeasesRetryInterval should small, so benchmark of findExpired will recheck expired lease.
    71  	le = newLessor(lg, be, nil, LessorConfig{MinLeaseTTL: -1000, ExpiredLeasesRetryInterval: 10 * time.Microsecond})
    72  	le.SetRangeDeleter(func() TxnDelete {
    73  		ftd := &FakeTxnDelete{be.BatchTx()}
    74  		ftd.Lock()
    75  		return ftd
    76  	})
    77  	le.Promote(0)
    78  
    79  	return le, func() {
    80  		le.Stop()
    81  		be.Close()
    82  	}
    83  }
    84  
    85  func benchmarkLessorGrant(benchSize int, b *testing.B) {
    86  	ttls := randomTTL(benchSize, minTTL, maxTTL)
    87  
    88  	var le *lessor
    89  	var tearDown func()
    90  
    91  	b.ResetTimer()
    92  	for i := 0; i < b.N; {
    93  		b.StopTimer()
    94  		if tearDown != nil {
    95  			tearDown()
    96  			tearDown = nil
    97  		}
    98  		le, tearDown = setUp(b)
    99  		b.StartTimer()
   100  
   101  		for j := 1; j <= benchSize; j++ {
   102  			le.Grant(LeaseID(j), ttls[j-1])
   103  		}
   104  		i += benchSize
   105  	}
   106  	b.StopTimer()
   107  
   108  	if tearDown != nil {
   109  		tearDown()
   110  	}
   111  }
   112  
   113  func benchmarkLessorRevoke(benchSize int, b *testing.B) {
   114  	ttls := randomTTL(benchSize, minTTL, maxTTL)
   115  
   116  	var le *lessor
   117  	var tearDown func()
   118  	b.ResetTimer()
   119  	for i := 0; i < b.N; i++ {
   120  		b.StopTimer()
   121  		if tearDown != nil {
   122  			tearDown()
   123  			tearDown = nil
   124  		}
   125  		le, tearDown = setUp(b)
   126  		for j := 1; j <= benchSize; j++ {
   127  			le.Grant(LeaseID(j), ttls[j-1])
   128  		}
   129  		b.StartTimer()
   130  
   131  		for j := 1; j <= benchSize; j++ {
   132  			le.Revoke(LeaseID(j))
   133  		}
   134  		i += benchSize
   135  	}
   136  	b.StopTimer()
   137  
   138  	if tearDown != nil {
   139  		tearDown()
   140  	}
   141  }
   142  
   143  func benchmarkLessorRenew(benchSize int, b *testing.B) {
   144  	ttls := randomTTL(benchSize, minTTL, maxTTL)
   145  
   146  	var le *lessor
   147  	var tearDown func()
   148  
   149  	b.ResetTimer()
   150  	for i := 0; i < b.N; {
   151  		b.StopTimer()
   152  		if tearDown != nil {
   153  			tearDown()
   154  			tearDown = nil
   155  		}
   156  		le, tearDown = setUp(b)
   157  		for j := 1; j <= benchSize; j++ {
   158  			le.Grant(LeaseID(j), ttls[j-1])
   159  		}
   160  		b.StartTimer()
   161  
   162  		for j := 1; j <= benchSize; j++ {
   163  			le.Renew(LeaseID(j))
   164  		}
   165  		i += benchSize
   166  	}
   167  	b.StopTimer()
   168  
   169  	if tearDown != nil {
   170  		tearDown()
   171  	}
   172  }
   173  
   174  func benchmarkLessorFindExpired(benchSize int, b *testing.B) {
   175  	// 50% lease are expired.
   176  	ttls := randomTTL(benchSize, -500, 500)
   177  	findExpiredLimit := 50
   178  
   179  	var le *lessor
   180  	var tearDown func()
   181  
   182  	b.ResetTimer()
   183  	for i := 0; i < b.N; {
   184  		b.StopTimer()
   185  		if tearDown != nil {
   186  			tearDown()
   187  			tearDown = nil
   188  		}
   189  		le, tearDown = setUp(b)
   190  		for j := 1; j <= benchSize; j++ {
   191  			le.Grant(LeaseID(j), ttls[j-1])
   192  		}
   193  		// lessor's runLoop should not call findExpired
   194  		demote(le)
   195  		b.StartTimer()
   196  
   197  		// refresh fixture after pop all expired lease
   198  		for ; ; i++ {
   199  			le.mu.Lock()
   200  			ls := le.findExpiredLeases(findExpiredLimit)
   201  			if len(ls) == 0 {
   202  				le.mu.Unlock()
   203  				break
   204  			}
   205  			le.mu.Unlock()
   206  
   207  			// simulation: revoke lease after expired
   208  			b.StopTimer()
   209  			for _, lease := range ls {
   210  				le.Revoke(lease.ID)
   211  			}
   212  			b.StartTimer()
   213  		}
   214  	}
   215  	b.StopTimer()
   216  
   217  	if tearDown != nil {
   218  		tearDown()
   219  	}
   220  }
   221  

View as plain text