github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/bench/tools/aisloader/namegetter/objnamegetter.go (about) 1 // Package namegetter is utility to generate filenames for aisloader PUT requests 2 /* 3 * Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved. 4 */ 5 package namegetter 6 7 import ( 8 "math/rand" 9 "sync" 10 11 "github.com/NVIDIA/aistore/cmn/cos" 12 ) 13 14 type ( 15 ObjectNameGetter interface { 16 ObjName() string 17 AddObjName(objName string) 18 Init(names []string, rnd *rand.Rand) 19 Names() []string 20 Len() int 21 } 22 RandomNameGetter struct { 23 rnd *rand.Rand 24 BaseNameGetter 25 } 26 RandomUniqueNameGetter struct { 27 BaseNameGetter 28 rnd *rand.Rand 29 bitmask []uint64 30 used int 31 } 32 RandomUniqueIterNameGetter struct { 33 BaseNameGetter 34 rnd *rand.Rand 35 bitmask []uint64 36 used int 37 } 38 PermutationUniqueNameGetter struct { 39 BaseNameGetter 40 rnd *rand.Rand 41 perm []int 42 permidx int 43 } 44 PermutationUniqueImprovedNameGetter struct { 45 BaseNameGetter 46 rnd *rand.Rand 47 perm []int 48 permNext []int 49 permidx int 50 nextReady sync.WaitGroup 51 } 52 BaseNameGetter struct { 53 names []string 54 } 55 ) 56 57 // RandomNameGetter // 58 59 func (rung *RandomNameGetter) Init(names []string, rnd *rand.Rand) { 60 rung.names = names 61 rung.rnd = rnd 62 } 63 64 func (rung *RandomNameGetter) AddObjName(objName string) { 65 rung.names = append(rung.names, objName) 66 } 67 68 func (rung *RandomNameGetter) ObjName() string { 69 idx := rung.rnd.Intn(len(rung.names)) 70 return rung.names[idx] 71 } 72 73 // RandomUniqueNameGetter // 74 75 func (rung *RandomUniqueNameGetter) Init(names []string, rnd *rand.Rand) { 76 rung.names = names 77 rung.rnd = rnd 78 79 lenBitmask := len(names) / 64 80 if len(names)%64 != 0 { 81 lenBitmask++ 82 } 83 84 rung.bitmask = make([]uint64, lenBitmask) 85 } 86 87 func (rung *RandomUniqueNameGetter) AddObjName(objName string) { 88 if len(rung.names)%64 == 0 { 89 rung.bitmask = append(rung.bitmask, uint64(0)) 90 } 91 rung.names = append(rung.names, objName) 92 } 93 94 func (rung *RandomUniqueNameGetter) ObjName() string { 95 if rung.used == len(rung.names) { 96 for i := range rung.bitmask { 97 rung.bitmask[i] = 0 98 } 99 rung.used = 0 100 } 101 102 for { 103 idx := rung.rnd.Intn(len(rung.names)) 104 bitmaskID := idx / 64 105 bitmaskBit := uint64(1) << uint64(idx%64) 106 if rung.bitmask[bitmaskID]&bitmaskBit == 0 { 107 rung.used++ 108 rung.bitmask[bitmaskID] |= bitmaskBit 109 return rung.names[idx] 110 } 111 } 112 } 113 114 // RandomUniqueIterNameGetter // 115 116 func (ruing *RandomUniqueIterNameGetter) Init(names []string, rnd *rand.Rand) { 117 ruing.names = names 118 ruing.rnd = rnd 119 120 lenBitmask := len(names) / 64 121 if len(names)%64 != 0 { 122 lenBitmask++ 123 } 124 125 ruing.bitmask = make([]uint64, lenBitmask) 126 } 127 128 func (ruing *RandomUniqueIterNameGetter) AddObjName(objName string) { 129 if len(ruing.names)%64 == 0 { 130 ruing.bitmask = append(ruing.bitmask, uint64(0)) 131 } 132 ruing.names = append(ruing.names, objName) 133 } 134 135 func (ruing *RandomUniqueIterNameGetter) ObjName() string { 136 if ruing.used == len(ruing.names) { 137 for i := range ruing.bitmask { 138 ruing.bitmask[i] = 0 139 } 140 ruing.used = 0 141 } 142 143 namesLen := len(ruing.names) 144 idx := ruing.rnd.Intn(namesLen) 145 146 for { 147 bitmaskID := idx / 64 148 bitmaskBit := uint64(1) << uint64(idx%64) 149 if ruing.bitmask[bitmaskID]&bitmaskBit == 0 { 150 ruing.bitmask[bitmaskID] |= bitmaskBit 151 ruing.used++ 152 return ruing.names[idx] 153 } 154 idx = (idx + 1) % namesLen 155 } 156 } 157 158 // PermutationUniqueNameGetter // 159 160 func (pung *PermutationUniqueNameGetter) Init(names []string, rnd *rand.Rand) { 161 pung.names = names 162 pung.rnd = rnd 163 pung.perm = pung.rnd.Perm(len(names)) 164 } 165 166 func (*PermutationUniqueNameGetter) AddObjName(string) { 167 cos.AssertMsg(false, "can't add object once PermutationUniqueNameGetter is initialized") 168 } 169 170 func (pung *PermutationUniqueNameGetter) ObjName() string { 171 if pung.permidx == len(pung.names) { 172 pung.permidx = 0 173 pung.perm = pung.rnd.Perm(len(pung.names)) 174 } 175 objName := pung.names[pung.perm[pung.permidx]] 176 pung.permidx++ 177 return objName 178 } 179 180 // PermutationUniqueImprovedNameGetter // 181 182 func (pung *PermutationUniqueImprovedNameGetter) Init(names []string, rnd *rand.Rand) { 183 pung.nextReady.Wait() // in case someone called Init twice, wait until initializing pung.permNext in ObjName() has finished 184 pung.names = names 185 pung.rnd = rnd 186 pung.perm = pung.rnd.Perm(len(names)) 187 pung.permNext = pung.rnd.Perm(len(names)) 188 } 189 190 func (*PermutationUniqueImprovedNameGetter) AddObjName(string) { 191 cos.AssertMsg(false, "can't add object once PermutationUniqueImprovedNameGetter is initialized") 192 } 193 194 func (pung *PermutationUniqueImprovedNameGetter) ObjName() string { 195 if pung.permidx == len(pung.names) { 196 pung.nextReady.Wait() 197 pung.perm, pung.permNext = pung.permNext, pung.perm 198 pung.permidx = 0 199 200 pung.nextReady.Add(1) 201 go func() { 202 pung.permNext = pung.rnd.Perm(len(pung.names)) 203 pung.nextReady.Done() 204 }() 205 } 206 objName := pung.names[pung.perm[pung.permidx]] 207 pung.permidx++ 208 return objName 209 } 210 211 // BaseNameGetter // 212 213 func (bng *BaseNameGetter) Names() []string { 214 return bng.names 215 } 216 217 func (bng *BaseNameGetter) Len() int { 218 if bng == nil || bng.names == nil { 219 return 0 220 } 221 return len(bng.names) 222 }