github.com/ZuluSpl0it/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  }