github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/memsys/d256_test.go (about) 1 // Package memsys provides memory management and Slab allocation 2 // with io.Reader and io.Writer interfaces on top of a scatter-gather lists 3 // (of reusable buffers) 4 /* 5 * Copyright (c) 2018-2024, NVIDIA CORPORATION. All rights reserved. 6 */ 7 package memsys_test 8 9 import ( 10 "io" 11 "os" 12 rdebug "runtime/debug" 13 "testing" 14 "time" 15 16 "github.com/NVIDIA/aistore/cmn/cos" 17 "github.com/NVIDIA/aistore/memsys" 18 ) 19 20 // 1. Run with all defaults: 21 // $ go test -bench=. -benchmem ./d256_test.go 22 // 23 // 2. Run a given bench for 30s: 24 // $ go test -bench=BenchmarkLargeAllocMax -benchtime=30s -benchmem ./d256_test.go 25 26 const ( 27 largeobj = cos.MiB * 8 28 smallobj = cos.KiB * 512 29 largefil = cos.GiB 30 ) 31 32 // largobj alloc 33 func BenchmarkLargeAllocMax(b *testing.B) { 34 benchAlloc(b, largeobj, memsys.MaxPageSlabSize) 35 } 36 37 func BenchmarkLargeAlloc128K(b *testing.B) { 38 benchAlloc(b, largeobj, cos.KiB*128) 39 } 40 41 func BenchmarkLargeAlloc64K(b *testing.B) { 42 benchAlloc(b, largeobj, cos.KiB*64) 43 } 44 45 func BenchmarkLargeAlloc32K(b *testing.B) { 46 benchAlloc(b, largeobj, cos.KiB*32) 47 } 48 49 // smallobj alloc 50 func BenchmarkSmallAllocMax(b *testing.B) { 51 benchAlloc(b, smallobj, memsys.MaxPageSlabSize) 52 } 53 54 func BenchmarkSmallAlloc128K(b *testing.B) { 55 benchAlloc(b, smallobj, cos.KiB*128) 56 } 57 58 func BenchmarkSmallAlloc64K(b *testing.B) { 59 benchAlloc(b, smallobj, cos.KiB*64) 60 } 61 62 func BenchmarkSmallAlloc32K(b *testing.B) { 63 benchAlloc(b, smallobj, cos.KiB*32) 64 } 65 66 func benchAlloc(b *testing.B, objsiz, sbufSize int64) { 67 mem := &memsys.MMSA{Name: "dmem", MinPctFree: 50} 68 mem.Init(0) 69 defer mem.Terminate(false) 70 71 // reset initial conditions & start b-timer 72 rdebug.FreeOSMemory() 73 b.ResetTimer() 74 75 for range b.N { 76 sgl := mem.NewSGL(objsiz, sbufSize) 77 _ = sgl 78 } 79 } 80 81 // largobj write 82 func BenchmarkLargeWriteMax(b *testing.B) { 83 benchWrite(b, largeobj, memsys.MaxPageSlabSize) 84 } 85 86 func BenchmarkLargeWrite128K(b *testing.B) { 87 benchWrite(b, largeobj, cos.KiB*128) 88 } 89 90 func BenchmarkLargeWrite64K(b *testing.B) { 91 benchWrite(b, largeobj, cos.KiB*64) 92 } 93 94 func BenchmarkLargeWrite32K(b *testing.B) { 95 benchWrite(b, largeobj, cos.KiB*32) 96 } 97 98 // smallobj write 99 func BenchmarkSmallWriteMax(b *testing.B) { 100 benchWrite(b, smallobj, memsys.MaxPageSlabSize) 101 } 102 103 func BenchmarkSmallWrite128K(b *testing.B) { 104 benchWrite(b, smallobj, cos.KiB*128) 105 } 106 107 func BenchmarkSmallWrite64K(b *testing.B) { 108 benchWrite(b, smallobj, cos.KiB*64) 109 } 110 111 func BenchmarkSmallWrite32K(b *testing.B) { 112 benchWrite(b, smallobj, cos.KiB*32) 113 } 114 115 func benchWrite(b *testing.B, objsiz, sbufSize int64) { 116 mem := &memsys.MMSA{Name: "emem", MinPctFree: 50} 117 mem.Init(0) 118 defer mem.Terminate(false) 119 120 // reset initial conditions & start b-timer 121 rdebug.FreeOSMemory() 122 buf := make([]byte, cos.KiB*128) 123 b.ResetTimer() 124 125 for range b.N { 126 sgl := mem.NewSGL(objsiz, sbufSize) 127 for siz := 0; siz < int(objsiz); siz += len(buf) { 128 sgl.Write(buf) 129 } 130 } 131 } 132 133 // largobj write => read => free 134 func BenchmarkLargeWRFMax(b *testing.B) { 135 benchWRF(b, largeobj, memsys.MaxPageSlabSize) 136 } 137 138 func BenchmarkLargeWRF128K(b *testing.B) { 139 benchWRF(b, largeobj, cos.KiB*128) 140 } 141 142 func BenchmarkLargeWRF64K(b *testing.B) { 143 benchWRF(b, largeobj, cos.KiB*64) 144 } 145 146 func BenchmarkLargeWRF32K(b *testing.B) { 147 benchWRF(b, largeobj, cos.KiB*32) 148 } 149 150 // smallobj write => read => free 151 func BenchmarkSmallWRFMax(b *testing.B) { 152 benchWRF(b, smallobj, memsys.MaxPageSlabSize) 153 } 154 155 func BenchmarkSmallWRF128K(b *testing.B) { 156 benchWRF(b, smallobj, cos.KiB*128) 157 } 158 159 func BenchmarkSmallWRF64K(b *testing.B) { 160 benchWRF(b, smallobj, cos.KiB*64) 161 } 162 163 func BenchmarkSmallWRF32K(b *testing.B) { 164 benchWRF(b, smallobj, cos.KiB*32) 165 } 166 167 func benchWRF(b *testing.B, objsiz, sbufSize int64) { 168 mem := &memsys.MMSA{Name: "fmem", MinPctFree: 50} 169 mem.Init(0) 170 defer mem.Terminate(false) 171 cha := make(chan *memsys.SGL, 1024*16) 172 173 // reset initial conditions 174 rdebug.FreeOSMemory() 175 l := cos.KiB * 128 176 buf := make([]byte, l) 177 178 // delayed sgl.Free 179 go func(cha chan *memsys.SGL) { 180 time.Sleep(time.Second * 5) 181 for { 182 sgl := <-cha 183 sgl.Free() 184 } 185 }(cha) 186 187 b.ResetTimer() // <==== start 188 189 for range b.N { 190 sgl := mem.NewSGL(objsiz, sbufSize) 191 for siz := 0; siz < int(objsiz); siz += l { 192 n, _ := sgl.Write(buf) 193 cos.Assert(n == l) 194 } 195 for siz := 0; siz < int(objsiz); siz += l { 196 n, _ := sgl.Read(buf) 197 cos.Assert(n == l) 198 } 199 select { 200 case cha <- sgl: 201 default: 202 } 203 } 204 b.StopTimer() // wo/ defers 205 } 206 207 // file read to sgl 208 func BenchmarkLargeFileMax(b *testing.B) { 209 benchFile(b, memsys.MaxPageSlabSize) 210 } 211 212 func BenchmarkLargeFile128K(b *testing.B) { 213 benchFile(b, cos.KiB*128) 214 } 215 216 func BenchmarkLargeFile64K(b *testing.B) { 217 benchFile(b, cos.KiB*64) 218 } 219 220 func BenchmarkLargeFile32K(b *testing.B) { 221 benchFile(b, cos.KiB*32) 222 } 223 224 func benchFile(b *testing.B, sbufSize int64) { 225 mem := &memsys.MMSA{Name: "gmem", MinPctFree: 50} 226 mem.Init(0) 227 defer mem.Terminate(false) 228 229 // reset initial conditions 230 rdebug.FreeOSMemory() 231 232 file, err := os.CreateTemp("/tmp", "") 233 if err != nil { 234 b.Fatal(err) 235 } 236 n, _ := file.Write(make([]byte, largefil)) 237 if int64(n) != largefil { 238 b.Fatal(n, largefil) 239 } 240 241 defer func() { 242 file.Close() 243 os.Remove(file.Name()) 244 }() 245 246 slab, err := mem.GetSlab(sbufSize) 247 cos.AssertNoErr(err) 248 buf := slab.Alloc() 249 defer slab.Free(buf) 250 251 if int64(len(buf)) != sbufSize { 252 b.Fatal(len(buf), sbufSize) 253 } 254 255 b.ResetTimer() // start timing it 256 for range b.N { 257 file.Seek(0, io.SeekStart) 258 n, _ := io.CopyBuffer(io.Discard, file, buf) 259 if n != largefil { 260 b.Fatal(n, largefil) 261 } 262 } 263 b.StopTimer() // wo/ defers 264 }