github.com/avfs/avfs@v0.33.1-0.20240303173310-c6ba67c33eb7/test/test_bench.go (about)

     1  //
     2  //  Copyright 2020 The AVFS authors
     3  //
     4  //  Licensed under the Apache License, Version 2.0 (the "License");
     5  //  you may not use this file except in compliance with the License.
     6  //  You may obtain a copy of the License at
     7  //
     8  //  	http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  //  Unless required by applicable law or agreed to in writing, software
    11  //  distributed under the License is distributed on an "AS IS" BASIS,
    12  //  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  //  See the License for the specific language governing permissions and
    14  //  limitations under the License.
    15  //
    16  
    17  package test
    18  
    19  import (
    20  	"io"
    21  	"math/rand"
    22  	"os"
    23  	"strconv"
    24  	"testing"
    25  
    26  	"github.com/avfs/avfs"
    27  )
    28  
    29  const (
    30  	bufSize     = 32 * 1024
    31  	maxFileSize = 1024 * bufSize
    32  )
    33  
    34  // BenchAll runs all benchmarks.
    35  func (ts *Suite) BenchAll(b *testing.B) {
    36  	ts.RunBenchmarks(b, UsrTest,
    37  		ts.BenchCreate,
    38  		ts.BenchFileRead,
    39  		ts.BenchFileWrite,
    40  		ts.BenchMkdir,
    41  		ts.BenchOpenFile,
    42  		ts.BenchRemove,
    43  	)
    44  }
    45  
    46  // benchOpenFlags returns the flags used to disable cache.
    47  func (ts *Suite) benchOpenFlags() int {
    48  	vfs := ts.vfsTest
    49  	if !vfs.HasFeature(avfs.FeatRealFS) || vfs.OSType() != avfs.OsLinux {
    50  		return 0
    51  	}
    52  
    53  	return 0x4000 // syscall.O_DIRECT for linux.
    54  }
    55  
    56  // BenchCreate benchmarks Create function.
    57  func (ts *Suite) BenchCreate(b *testing.B, testDir string) {
    58  	vfs := ts.vfsTest
    59  
    60  	b.Run("Create", func(b *testing.B) {
    61  		b.StopTimer()
    62  
    63  		files := make([]string, b.N)
    64  
    65  		for n := 0; n < b.N; n++ {
    66  			path := vfs.Join(testDir, strconv.FormatUint(uint64(n), 10))
    67  			files[n] = path
    68  		}
    69  
    70  		b.StartTimer()
    71  
    72  		for n := 0; n < b.N; n++ {
    73  			fileName := files[n]
    74  
    75  			f, err := vfs.Create(fileName)
    76  			RequireNoError(b, err, "Create %s", fileName)
    77  
    78  			_ = f.Close()
    79  		}
    80  	})
    81  }
    82  
    83  func (ts *Suite) BenchFileRead(b *testing.B, testDir string) {
    84  	vfs := ts.vfsTest
    85  	buf := make([]byte, bufSize)
    86  	fileName := vfs.Join(testDir, "BenchFileRead.txt")
    87  
    88  	err := vfs.WriteFile(fileName, make([]byte, maxFileSize), avfs.DefaultFilePerm)
    89  	RequireNoError(b, err, "WriteFile %s", fileName)
    90  
    91  	f, err := vfs.OpenFile(fileName, os.O_RDONLY|ts.benchOpenFlags(), avfs.DefaultFilePerm)
    92  	RequireNoError(b, err, "OpenFile %s", fileName)
    93  
    94  	defer func() {
    95  		_ = f.Close()
    96  		_ = vfs.Remove(fileName)
    97  	}()
    98  
    99  	b.ResetTimer()
   100  
   101  	b.Run("FileRead", func(b *testing.B) {
   102  		_, err = f.Seek(0, io.SeekStart)
   103  		RequireNoError(b, err, "Seek %s", fileName)
   104  
   105  		s := 0
   106  
   107  		for n := 0; n < b.N; n++ {
   108  			if s >= maxFileSize {
   109  				s = 0
   110  				_, err = f.Seek(0, io.SeekStart)
   111  				RequireNoError(b, err, "Seek %s", fileName)
   112  			}
   113  
   114  			_, err = f.Read(buf)
   115  			RequireNoError(b, err, "Read %s", fileName)
   116  
   117  			s += bufSize
   118  		}
   119  	})
   120  }
   121  
   122  func (ts *Suite) BenchFileWrite(b *testing.B, testDir string) {
   123  	vfs := ts.vfsTest
   124  	buf := make([]byte, bufSize)
   125  	fileName := vfs.Join(testDir, "BenchFileWrite.txt")
   126  
   127  	f, err := vfs.OpenFile(fileName, os.O_CREATE|os.O_WRONLY|ts.benchOpenFlags(), avfs.DefaultFilePerm)
   128  	RequireNoError(b, err, "OpenFile %s", fileName)
   129  
   130  	defer func() {
   131  		_ = f.Close()
   132  		_ = vfs.Remove(fileName)
   133  	}()
   134  
   135  	b.ResetTimer()
   136  
   137  	b.Run("FileWrite", func(b *testing.B) {
   138  		s := 0
   139  
   140  		for n := 0; n < b.N; n++ {
   141  			s += bufSize
   142  			if s >= maxFileSize {
   143  				s = 0
   144  				_, err = f.Seek(0, io.SeekStart)
   145  				RequireNoError(b, err, "Seek %s", fileName)
   146  			}
   147  
   148  			_, err = f.Write(buf)
   149  			RequireNoError(b, err, "Write %s", fileName)
   150  		}
   151  	})
   152  }
   153  
   154  // BenchMkdir benchmarks Mkdir function.
   155  func (ts *Suite) BenchMkdir(b *testing.B, testDir string) {
   156  	vfs := ts.vfsTest
   157  
   158  	b.Run("Mkdir", func(b *testing.B) {
   159  		b.StopTimer()
   160  
   161  		dirs := make([]string, b.N)
   162  		dirs[0] = testDir
   163  
   164  		for n := 1; n < b.N; n++ {
   165  			parent := dirs[rand.Intn(n)]
   166  			path := vfs.Join(parent, strconv.FormatUint(rand.Uint64(), 10))
   167  			dirs[n] = path
   168  		}
   169  
   170  		err := vfs.RemoveAll(testDir)
   171  		RequireNoError(b, err, "RemoveAll %s", testDir)
   172  
   173  		b.StartTimer()
   174  
   175  		for n := 0; n < b.N; n++ {
   176  			err = vfs.Mkdir(dirs[n], avfs.DefaultDirPerm)
   177  			RequireNoError(b, err, "Mkdir %s", dirs[n])
   178  		}
   179  	})
   180  }
   181  
   182  // BenchOpenFile benchmarks OpenFile function.
   183  func (ts *Suite) BenchOpenFile(b *testing.B, testDir string) {
   184  	vfs := ts.vfsTest
   185  	fileName := ts.existingFile(b, testDir, nil)
   186  
   187  	b.ResetTimer()
   188  
   189  	b.Run("Open", func(b *testing.B) {
   190  		for n := 1; n < b.N; n++ {
   191  			f, err := vfs.OpenFile(fileName, os.O_RDONLY, avfs.DefaultFilePerm)
   192  			RequireNoError(b, err, "OpenFile %s", fileName)
   193  
   194  			_ = f.Close()
   195  		}
   196  	})
   197  }
   198  
   199  // BenchRemove benchmarks Remove function.
   200  func (ts *Suite) BenchRemove(b *testing.B, testDir string) {
   201  	vfs := ts.vfsTest
   202  
   203  	b.Run("Remove", func(b *testing.B) {
   204  		b.StopTimer()
   205  
   206  		rt := avfs.NewRndTree(vfs, &avfs.RndTreeOpts{NbDirs: b.N})
   207  
   208  		err := rt.CreateTree(testDir)
   209  		RequireNoError(b, err, "CreateTree %s", testDir)
   210  
   211  		dirs := rt.Dirs()
   212  
   213  		b.StartTimer()
   214  
   215  		for n := b.N - 1; n > 0; n-- {
   216  			path := dirs[n].Name
   217  
   218  			err = vfs.Remove(path)
   219  			RequireNoError(b, err, "Remove %s", path)
   220  		}
   221  	})
   222  }