github.com/nebulouslabs/sia@v1.3.7/persist/disk_test.go (about) 1 package persist 2 3 // disk_test.go probes some of the disk operations that are very commonly used 4 // within Sia. Namely, Read, Write, Truncate, WriteAt(rand), ReadAt(rand). 5 6 import ( 7 "os" 8 "path/filepath" 9 "testing" 10 11 "github.com/NebulousLabs/Sia/build" 12 13 "github.com/NebulousLabs/fastrand" 14 ) 15 16 // BenchmarkWrite512MiB checks how long it takes to write 512MiB sequentially. 17 func BenchmarkWrite512MiB(b *testing.B) { 18 testDir := build.TempDir("persist", b.Name()) 19 err := os.MkdirAll(testDir, 0700) 20 if err != nil { 21 b.Fatal(err) 22 } 23 24 b.SetBytes(1 << 29) 25 filename := filepath.Join(testDir, "512MiB.file") 26 b.ResetTimer() 27 for i := 0; i < b.N; i++ { 28 // Make the file. 29 f, err := os.Create(filename) 30 if err != nil { 31 b.Fatal(err) 32 } 33 34 // 2^12 writes of 4MiB. 35 for i := 0; i < 1<<7; i++ { 36 // Get the entropy separate from the timer. 37 b.StopTimer() 38 data := fastrand.Bytes(1 << 22) 39 b.StartTimer() 40 _, err = f.Write(data) 41 if err != nil { 42 b.Fatal(err) 43 } 44 // Sync after every write. 45 err = f.Sync() 46 if err != nil { 47 b.Fatal(err) 48 } 49 } 50 51 // Close the file before iterating. 52 err = f.Close() 53 if err != nil { 54 b.Fatal(err) 55 } 56 } 57 58 err = os.Remove(filename) 59 if err != nil { 60 b.Fatal(err) 61 } 62 } 63 64 // BenchmarkWrite512MiBTrunc checks how long it takes to write 512MiB using 65 // stepwise truncate. 66 func BenchmarkWrite512MiBTrunc(b *testing.B) { 67 testDir := build.TempDir("persist", b.Name()) 68 err := os.MkdirAll(testDir, 0700) 69 if err != nil { 70 b.Fatal(err) 71 } 72 73 b.SetBytes(1 << 29) 74 filename := filepath.Join(testDir, "512MiB.file") 75 b.ResetTimer() 76 for i := 0; i < b.N; i++ { 77 // Make the file. 78 f, err := os.Create(filename) 79 if err != nil { 80 b.Fatal(err) 81 } 82 83 // 2^12 writes of 4MiB. 84 for i := 0; i < 1<<7; i++ { 85 // Extend the file through truncation. 86 err = f.Truncate(int64((i + 1) * 1 << 22)) 87 if err != nil { 88 b.Fatal(err) 89 } 90 // Sync after every write. 91 err = f.Sync() 92 if err != nil { 93 b.Fatal(err) 94 } 95 } 96 97 // Close the file before iterating. 98 err = f.Close() 99 if err != nil { 100 b.Fatal(err) 101 } 102 } 103 104 err = os.Remove(filename) 105 if err != nil { 106 b.Fatal(err) 107 } 108 } 109 110 // BenchmarkWrite512MiBRand checks how long it takes to write 512MiB randomly. 111 func BenchmarkWrite512MiBRand(b *testing.B) { 112 testDir := build.TempDir("persist", b.Name()) 113 err := os.MkdirAll(testDir, 0700) 114 if err != nil { 115 b.Fatal(err) 116 } 117 b.SetBytes(1 << 29) 118 filename := filepath.Join(testDir, "512MiB.file") 119 b.ResetTimer() 120 for i := 0; i < b.N; i++ { 121 // Make the file. 122 f, err := os.Create(filename) 123 if err != nil { 124 b.Fatal(err) 125 } 126 127 // 2^7 writes of 4MiB. 128 for i := 0; i < 1<<7; i++ { 129 // Get the entropy separate from the timer. 130 b.StopTimer() 131 data := fastrand.Bytes(1 << 22) 132 offset := int64(fastrand.Intn(1 << 6)) 133 offset *= 1 << 22 134 b.StartTimer() 135 _, err = f.WriteAt(data, offset) 136 if err != nil { 137 b.Fatal(err) 138 } 139 // Sync after every write. 140 err = f.Sync() 141 if err != nil { 142 b.Fatal(err) 143 } 144 } 145 146 // Close the file before iterating. 147 err = f.Close() 148 if err != nil { 149 b.Fatal(err) 150 } 151 } 152 153 err = os.Remove(filename) 154 if err != nil { 155 b.Fatal(err) 156 } 157 } 158 159 // BenchmarkRead512MiB checks how long it takes to read 512MiB sequentially. 160 func BenchmarkRead512MiB(b *testing.B) { 161 testDir := build.TempDir("persist", b.Name()) 162 err := os.MkdirAll(testDir, 0700) 163 if err != nil { 164 b.Fatal(err) 165 } 166 b.SetBytes(1 << 29) 167 168 // Make the file. 169 filename := filepath.Join(testDir, "512MiB.file") 170 f, err := os.Create(filename) 171 if err != nil { 172 b.Fatal(err) 173 } 174 175 // 2^7 writes of 4MiB. 176 for i := 0; i < 1<<7; i++ { 177 // Get the entropy separate from the timer. 178 b.StopTimer() 179 data := fastrand.Bytes(1 << 22) 180 b.StartTimer() 181 _, err = f.Write(data) 182 if err != nil { 183 b.Fatal(err) 184 } 185 // Sync after every write. 186 err = f.Sync() 187 if err != nil { 188 b.Fatal(err) 189 } 190 } 191 192 // Close the file. 193 err = f.Close() 194 if err != nil { 195 b.Fatal(err) 196 } 197 198 // Check the sequential read speed. 199 b.ResetTimer() 200 for i := 0; i < b.N; i++ { 201 // Open the file. 202 f, err := os.Open(filename) 203 if err != nil { 204 b.Fatal(err) 205 } 206 207 // Read the file 4 MiB at a time. 208 for i := 0; i < 1<<6; i++ { 209 data := make([]byte, 1<<22) 210 _, err = f.Read(data) 211 if err != nil { 212 b.Fatal(err) 213 } 214 } 215 216 err = f.Close() 217 if err != nil { 218 b.Fatal(err) 219 } 220 } 221 222 err = os.Remove(filename) 223 if err != nil { 224 b.Fatal(err) 225 } 226 } 227 228 // BenchmarkRead512MiBRand checks how long it takes to read 512MiB randomly. 229 func BenchmarkRead512MiBRand(b *testing.B) { 230 testDir := build.TempDir("persist", b.Name()) 231 err := os.MkdirAll(testDir, 0700) 232 if err != nil { 233 b.Fatal(err) 234 } 235 b.SetBytes(1 << 29) 236 237 // Make the file. 238 filename := filepath.Join(testDir, "512MiB.file") 239 f, err := os.Create(filename) 240 if err != nil { 241 b.Fatal(err) 242 } 243 244 // 2^7 writes of 4MiB. 245 for i := 0; i < 1<<7; i++ { 246 // Get the entropy separate from the timer. 247 b.StopTimer() 248 data := fastrand.Bytes(1 << 22) 249 b.StartTimer() 250 _, err = f.Write(data) 251 if err != nil { 252 b.Fatal(err) 253 } 254 // Sync after every write. 255 err = f.Sync() 256 if err != nil { 257 b.Fatal(err) 258 } 259 } 260 261 // Close the file. 262 err = f.Close() 263 if err != nil { 264 b.Fatal(err) 265 } 266 267 // Check the sequential read speed. 268 b.ResetTimer() 269 for i := 0; i < b.N; i++ { 270 // Open the file. 271 f, err := os.Open(filename) 272 if err != nil { 273 b.Fatal(err) 274 } 275 276 // Read the file 4 MiB at a time. 277 for i := 0; i < 1<<6; i++ { 278 offset := int64(fastrand.Intn(1 << 6)) 279 offset *= 1 << 22 280 data := make([]byte, 1<<22) 281 _, err = f.ReadAt(data, offset) 282 if err != nil { 283 b.Fatal(err) 284 } 285 } 286 287 err = f.Close() 288 if err != nil { 289 b.Fatal(err) 290 } 291 } 292 293 err = os.Remove(filename) 294 if err != nil { 295 b.Fatal(err) 296 } 297 } 298 299 // BenchmarkTruncate512MiB checks how long it takes to truncate a 512 MiB file. 300 func BenchmarkTruncate512MiB(b *testing.B) { 301 testDir := build.TempDir("persist", b.Name()) 302 err := os.MkdirAll(testDir, 0700) 303 if err != nil { 304 b.Fatal(err) 305 } 306 b.SetBytes(1 << 29) 307 filename := filepath.Join(testDir, "512MiB.file") 308 // Check the truncate speed. 309 b.ResetTimer() 310 for i := 0; i < b.N; i++ { 311 // Make the file separate from the timer. 312 b.StopTimer() 313 f, err := os.Create(filename) 314 if err != nil { 315 b.Fatal(err) 316 } 317 318 // 2^7 writes of 4MiB. 319 for i := 0; i < 1<<7; i++ { 320 // Get the entropy separate from the timer. 321 b.StopTimer() 322 data := fastrand.Bytes(1 << 22) 323 b.StartTimer() 324 _, err = f.Write(data) 325 if err != nil { 326 b.Fatal(err) 327 } 328 } 329 // Sync after writing. 330 err = f.Sync() 331 if err != nil { 332 b.Fatal(err) 333 } 334 335 // Close the file. 336 err = f.Close() 337 if err != nil { 338 b.Fatal(err) 339 } 340 b.StartTimer() 341 342 // Open the file. 343 f, err = os.OpenFile(filename, os.O_RDWR, 0600) 344 if err != nil { 345 b.Fatal(err) 346 } 347 348 // Truncate the file. 349 err = f.Truncate(0) 350 if err != nil { 351 b.Fatal(err) 352 } 353 354 // Sync. 355 err = f.Sync() 356 if err != nil { 357 b.Fatal(err) 358 } 359 360 // Close. 361 err = f.Close() 362 if err != nil { 363 b.Fatal(err) 364 } 365 } 366 367 err = os.Remove(filename) 368 if err != nil { 369 b.Fatal(err) 370 } 371 }