github.com/aaabigfish/gopkg@v1.1.0/syncx/rwmutex_test.go (about) 1 // Copyright 2021 ByteDance Inc. 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 syncx 16 17 import ( 18 "fmt" 19 "math/rand" 20 "sync" 21 "testing" 22 ) 23 24 func BenchmarkRWMutex100Read(b *testing.B) { 25 for nWorker := 1; nWorker <= 256; nWorker <<= 2 { 26 b.Run(fmt.Sprintf("syncx-%d", nWorker), func(b *testing.B) { 27 benchmarkSyncxRWMutexNWriteNRead(b, nWorker, 0) 28 }) 29 30 b.Run(fmt.Sprintf("sync-%d", nWorker), func(b *testing.B) { 31 benchmarkSyncRWMutexNWriteNRead(b, nWorker, 0) 32 }) 33 } 34 } 35 36 func BenchmarkRWMutex1Write99Read(b *testing.B) { 37 for nWorker := 1; nWorker <= 256; nWorker <<= 2 { 38 b.Run(fmt.Sprintf("syncx-%d", nWorker), func(b *testing.B) { 39 benchmarkSyncxRWMutexNWriteNRead(b, nWorker, 1) 40 }) 41 42 b.Run(fmt.Sprintf("sync-%d", nWorker), func(b *testing.B) { 43 benchmarkSyncRWMutexNWriteNRead(b, nWorker, 1) 44 }) 45 } 46 } 47 48 func BenchmarkRWMutex10Write90Read(b *testing.B) { 49 for nWorker := 1; nWorker <= 256; nWorker <<= 2 { 50 b.Run(fmt.Sprintf("syncx-%d", nWorker), func(b *testing.B) { 51 benchmarkSyncxRWMutexNWriteNRead(b, nWorker, 10) 52 }) 53 54 b.Run(fmt.Sprintf("sync-%d", nWorker), func(b *testing.B) { 55 benchmarkSyncRWMutexNWriteNRead(b, nWorker, 10) 56 }) 57 } 58 } 59 60 func BenchmarkRWMutex50Write50Read(b *testing.B) { 61 for nWorker := 1; nWorker <= 256; nWorker <<= 2 { 62 b.Run(fmt.Sprintf("syncx-%d", nWorker), func(b *testing.B) { 63 benchmarkSyncxRWMutexNWriteNRead(b, nWorker, 50) 64 }) 65 66 b.Run(fmt.Sprintf("sync-%d", nWorker), func(b *testing.B) { 67 benchmarkSyncRWMutexNWriteNRead(b, nWorker, 50) 68 }) 69 } 70 } 71 72 func benchmarkSyncRWMutexNWriteNRead(b *testing.B, nWorker, nWrite int) { 73 var res int // A mock resource we contention for 74 75 var mu sync.RWMutex 76 mu.Lock() 77 78 var wg sync.WaitGroup 79 wg.Add(nWorker) 80 81 n := b.N 82 quota := n / nWorker 83 84 for g := nWorker; g > 0; g-- { 85 // Comuse remaining quota 86 if g == 1 { 87 quota = n 88 } 89 go func(quota int) { 90 for i := 0; i < quota; i++ { 91 if rand.Intn(100) > nWrite-1 { 92 mu.RLock() 93 _ = res 94 mu.RUnlock() 95 } else { 96 mu.Lock() 97 res++ 98 mu.Unlock() 99 } 100 } 101 wg.Done() 102 }(quota) 103 104 n -= quota 105 } 106 107 if n != 0 { 108 b.Fatalf("Incorrect quota assignments: %v remaining", n) 109 } 110 111 b.ResetTimer() 112 mu.Unlock() 113 wg.Wait() 114 } 115 116 func benchmarkSyncxRWMutexNWriteNRead(b *testing.B, nWorker, nWrite int) { 117 var res int // A mock resource we contention for 118 119 mu := NewRWMutex() 120 mu.Lock() 121 122 var wg sync.WaitGroup 123 wg.Add(nWorker) 124 125 n := b.N 126 quota := n / nWorker 127 128 for g := nWorker; g > 0; g-- { 129 // Comuse remaining quota 130 if g == 1 { 131 quota = n 132 } 133 go func(quota int) { 134 rmu := mu.RLocker() 135 for i := 0; i < quota; i++ { 136 if rand.Intn(100) > nWrite-1 { 137 rmu.Lock() 138 _ = res 139 rmu.Unlock() 140 } else { 141 mu.Lock() 142 res++ 143 mu.Unlock() 144 } 145 } 146 wg.Done() 147 }(quota) 148 149 n -= quota 150 } 151 152 if n != 0 { 153 b.Fatalf("Incorrect quota assignments: %v remaining", n) 154 } 155 156 b.ResetTimer() 157 mu.Unlock() 158 wg.Wait() 159 }