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  }