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 }