github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/ais/tgtobj_internal_test.go (about)

     1  // Package ais provides core functionality for the AIStore object storage.
     2  /*
     3   * Copyright (c) 2018-2024, NVIDIA CORPORATION. All rights reserved.
     4   */
     5  package ais
     6  
     7  import (
     8  	"flag"
     9  	"io"
    10  	"net/http"
    11  	"os"
    12  	"path"
    13  	"testing"
    14  	"time"
    15  
    16  	"github.com/NVIDIA/aistore/api/apc"
    17  	"github.com/NVIDIA/aistore/cmn"
    18  	"github.com/NVIDIA/aistore/cmn/cos"
    19  	"github.com/NVIDIA/aistore/core"
    20  	"github.com/NVIDIA/aistore/core/meta"
    21  	"github.com/NVIDIA/aistore/core/mock"
    22  	"github.com/NVIDIA/aistore/fs"
    23  	"github.com/NVIDIA/aistore/tools/readers"
    24  )
    25  
    26  const (
    27  	testMountpath = "/tmp/ais-test-mpath" // mpath is created and deleted during the test
    28  	testBucket    = "bck"
    29  )
    30  
    31  var (
    32  	t *target
    33  
    34  	// interface guard
    35  	_ http.ResponseWriter = (*discardRW)(nil)
    36  )
    37  
    38  type (
    39  	discardRW struct {
    40  		w io.Writer
    41  	}
    42  )
    43  
    44  func newDiscardRW() *discardRW {
    45  	return &discardRW{
    46  		w: io.Discard,
    47  	}
    48  }
    49  
    50  func (drw *discardRW) Write(p []byte) (int, error) { return drw.w.Write(p) }
    51  func (*discardRW) Header() http.Header             { return make(http.Header) }
    52  func (*discardRW) WriteHeader(int)                 {}
    53  
    54  func TestMain(m *testing.M) {
    55  	flag.Parse()
    56  
    57  	// file system
    58  	cos.CreateDir(testMountpath)
    59  	defer os.RemoveAll(testMountpath)
    60  	fs.TestNew(nil)
    61  	fs.CSM.Reg(fs.ObjectType, &fs.ObjectContentResolver{}, true)
    62  	fs.CSM.Reg(fs.WorkfileType, &fs.WorkfileContentResolver{}, true)
    63  
    64  	// target
    65  	config := cmn.GCO.Get()
    66  	config.Log.Level = "3"
    67  	co := newConfigOwner(config)
    68  	t = newTarget(co)
    69  	t.initSnode(config)
    70  	tid, _ := initTID(config)
    71  	t.si.Init(tid, apc.Target)
    72  
    73  	fs.Add(testMountpath, t.SID())
    74  
    75  	t.htrun.init(config)
    76  
    77  	t.statsT = mock.NewStatsTracker()
    78  	core.Tinit(t, t.statsT, false)
    79  
    80  	bck := meta.NewBck(testBucket, apc.AIS, cmn.NsGlobal)
    81  	bmd := newBucketMD()
    82  	bmd.add(bck, &cmn.Bprops{
    83  		Cksum: cmn.CksumConf{
    84  			Type: cos.ChecksumNone,
    85  		},
    86  	})
    87  	t.owner.bmd.putPersist(bmd, nil)
    88  	fs.CreateBucket(bck.Bucket(), false /*nilbmd*/)
    89  
    90  	m.Run()
    91  }
    92  
    93  func BenchmarkObjPut(b *testing.B) {
    94  	benches := []struct {
    95  		fileSize int64
    96  	}{
    97  		{cos.KiB},
    98  		{512 * cos.KiB},
    99  		{cos.MiB},
   100  		{2 * cos.MiB},
   101  		{4 * cos.MiB},
   102  		{8 * cos.MiB},
   103  		{16 * cos.MiB},
   104  	}
   105  	for _, bench := range benches {
   106  		b.Run(cos.ToSizeIEC(bench.fileSize, 2), func(b *testing.B) {
   107  			lom := core.AllocLOM("objname")
   108  			defer core.FreeLOM(lom)
   109  			err := lom.InitBck(&cmn.Bck{Name: testBucket, Provider: apc.AIS, Ns: cmn.NsGlobal})
   110  			if err != nil {
   111  				b.Fatal(err)
   112  			}
   113  
   114  			b.ResetTimer()
   115  			for range b.N {
   116  				b.StopTimer()
   117  				r, _ := readers.NewRand(bench.fileSize, cos.ChecksumNone)
   118  				poi := &putOI{
   119  					atime:   time.Now().UnixNano(),
   120  					t:       t,
   121  					lom:     lom,
   122  					r:       r,
   123  					workFQN: path.Join(testMountpath, "objname.work"),
   124  					config:  cmn.GCO.Get(),
   125  				}
   126  				os.Remove(lom.FQN)
   127  				b.StartTimer()
   128  
   129  				_, err := poi.putObject()
   130  				if err != nil {
   131  					b.Fatal(err)
   132  				}
   133  			}
   134  			b.StopTimer()
   135  			os.Remove(lom.FQN)
   136  		})
   137  	}
   138  }
   139  
   140  func BenchmarkObjAppend(b *testing.B) {
   141  	benches := []struct {
   142  		fileSize int64
   143  	}{
   144  		{fileSize: cos.KiB},
   145  		{fileSize: 512 * cos.KiB},
   146  		{fileSize: cos.MiB},
   147  		{fileSize: 2 * cos.MiB},
   148  		{fileSize: 4 * cos.MiB},
   149  		{fileSize: 8 * cos.MiB},
   150  		{fileSize: 16 * cos.MiB},
   151  	}
   152  
   153  	buf := make([]byte, 16*cos.KiB)
   154  	for _, bench := range benches {
   155  		b.Run(cos.ToSizeIEC(bench.fileSize, 2), func(b *testing.B) {
   156  			lom := core.AllocLOM("objname")
   157  			defer core.FreeLOM(lom)
   158  			err := lom.InitBck(&cmn.Bck{Name: testBucket, Provider: apc.AIS, Ns: cmn.NsGlobal})
   159  			if err != nil {
   160  				b.Fatal(err)
   161  			}
   162  
   163  			var hdl aoHdl
   164  			b.ResetTimer()
   165  			for range b.N {
   166  				b.StopTimer()
   167  				r, _ := readers.NewRand(bench.fileSize, cos.ChecksumNone)
   168  				aoi := &apndOI{
   169  					started: time.Now().UnixNano(),
   170  					t:       t,
   171  					lom:     lom,
   172  					r:       r,
   173  					op:      apc.AppendOp,
   174  					hdl:     hdl,
   175  				}
   176  				os.Remove(lom.FQN)
   177  				b.StartTimer()
   178  
   179  				newHandle, _, err := aoi.apnd(buf)
   180  				if err != nil {
   181  					b.Fatal(err)
   182  				}
   183  				err = aoi.parse(newHandle)
   184  				if err != nil {
   185  					b.Fatal(err)
   186  				}
   187  			}
   188  			b.StopTimer()
   189  			os.Remove(lom.FQN)
   190  			os.Remove(hdl.workFQN)
   191  		})
   192  	}
   193  }
   194  
   195  func BenchmarkObjGetDiscard(b *testing.B) {
   196  	benches := []struct {
   197  		fileSize int64
   198  		chunked  bool
   199  	}{
   200  		{fileSize: cos.KiB, chunked: false},
   201  		{fileSize: 512 * cos.KiB, chunked: false},
   202  		{fileSize: cos.MiB, chunked: false},
   203  		{fileSize: 2 * cos.MiB, chunked: false},
   204  		{fileSize: 4 * cos.MiB, chunked: false},
   205  		{fileSize: 16 * cos.MiB, chunked: false},
   206  
   207  		{fileSize: cos.KiB, chunked: true},
   208  		{fileSize: 512 * cos.KiB, chunked: true},
   209  		{fileSize: cos.MiB, chunked: true},
   210  		{fileSize: 2 * cos.MiB, chunked: true},
   211  		{fileSize: 4 * cos.MiB, chunked: true},
   212  		{fileSize: 16 * cos.MiB, chunked: true},
   213  	}
   214  
   215  	for _, bench := range benches {
   216  		benchName := cos.ToSizeIEC(bench.fileSize, 2)
   217  		if bench.chunked {
   218  			benchName += "-chunked"
   219  		}
   220  		b.Run(benchName, func(b *testing.B) {
   221  			lom := core.AllocLOM("objname")
   222  			defer core.FreeLOM(lom)
   223  			err := lom.InitBck(&cmn.Bck{Name: testBucket, Provider: apc.AIS, Ns: cmn.NsGlobal})
   224  			if err != nil {
   225  				b.Fatal(err)
   226  			}
   227  
   228  			r, _ := readers.NewRand(bench.fileSize, cos.ChecksumNone)
   229  			poi := &putOI{
   230  				atime:   time.Now().UnixNano(),
   231  				t:       t,
   232  				lom:     lom,
   233  				r:       r,
   234  				workFQN: path.Join(testMountpath, "objname.work"),
   235  				config:  cmn.GCO.Get(),
   236  			}
   237  			_, err = poi.putObject()
   238  			if err != nil {
   239  				b.Fatal(err)
   240  			}
   241  
   242  			if err := lom.Load(false, false); err != nil {
   243  				b.Fatal(err)
   244  			}
   245  
   246  			w := newDiscardRW()
   247  			goi := &getOI{
   248  				atime:   time.Now().UnixNano(),
   249  				t:       t,
   250  				lom:     lom,
   251  				w:       w,
   252  				chunked: bench.chunked,
   253  			}
   254  
   255  			b.ResetTimer()
   256  			for range b.N {
   257  				_, err := goi.getObject()
   258  				if err != nil {
   259  					b.Fatal(err)
   260  				}
   261  			}
   262  
   263  			b.StopTimer()
   264  			os.Remove(lom.FQN)
   265  		})
   266  	}
   267  }