Skip to content

Instantly share code, notes, and snippets.

@komuw
Last active July 7, 2021 15:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save komuw/c152a73a1aae766873dee1e49f7730bf to your computer and use it in GitHub Desktop.
Save komuw/c152a73a1aae766873dee1e49f7730bf to your computer and use it in GitHub Desktop.
Benchmark fdatasync vs fsync
package main
import (
"log"
"math/rand"
"os"
"syscall"
"testing"
"time"
"golang.org/x/sys/unix"
)
const theFile = "/tmp/theFileBenchMarkFile.txt"
const fSize = 50 * 1024 * 1024 // 50Mb
func randString(length int) []byte {
var source = rand.NewSource(time.Now().UnixNano())
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
b := make([]byte, length)
for i := range b {
b[i] = charset[source.Int63()%int64(len(charset))]
}
return b
}
func fsync_stdlib() {
f, err := os.Create(theFile)
if err != nil {
log.Fatalln("unable to open file:", err)
}
_, err = f.Write(randString(fSize))
if err != nil {
log.Fatalln("unable to write to file:", err)
}
err = f.Sync()
if err != nil {
log.Fatalln("unable to Sync file:", err)
}
err = f.Close()
if err != nil {
log.Fatalln("unable to Close file:", err)
}
}
func fsync_x_sys() {
f, err := os.Create(theFile)
if err != nil {
log.Fatalln("unable to open file:", err)
}
_, err = f.Write(randString(fSize))
if err != nil {
log.Fatalln("unable to write to file:", err)
}
err = unix.Fsync(int(f.Fd()))
if err != nil {
log.Fatalln("unable to Sync file:", err)
}
err = f.Close()
if err != nil {
log.Fatalln("unable to Close file:", err)
}
}
func fdatasync_stdlib() {
f, err := os.Create(theFile)
if err != nil {
log.Fatalln("unable to open file:", err)
}
_, err = f.Write(randString(fSize))
if err != nil {
log.Fatalln("unable to write to file:", err)
}
// fdatasync() [...] does not flush modified metadata unless that metadata is needed in order to allow a subsequent data retrieval to be correctly handled. [...]
// On the other hand, a change to the file size (st_size, as made by say ftruncate(2)), would require a metadata flush.
//
// Note: sync of file does not also sync its directory.
// The directory needs to also be synced
err = syscall.Fdatasync(int(f.Fd()))
if err != nil {
log.Fatalln("unable to Fdatasync file:", err)
}
err = f.Close()
if err != nil {
log.Fatalln("unable to Close file:", err)
}
}
func fdatasync_x_sys() {
f, err := os.Create(theFile)
if err != nil {
log.Fatalln("unable to open file:", err)
}
_, err = f.Write(randString(fSize))
if err != nil {
log.Fatalln("unable to write to file:", err)
}
err = unix.Fdatasync(int(f.Fd()))
if err != nil {
log.Fatalln("unable to Fdatasync file:", err)
}
err = f.Close()
if err != nil {
log.Fatalln("unable to Close file:", err)
}
}
func removeFile() {
_ = os.Remove(theFile)
}
func BenchmarkFSync_stdlib(b *testing.B) {
removeFile()
b.ResetTimer()
for i := 0; i < b.N; i++ {
fsync_stdlib()
}
}
func BenchmarkFSync_x_sys(b *testing.B) {
removeFile()
b.ResetTimer()
for i := 0; i < b.N; i++ {
fsync_x_sys()
}
}
func BenchmarkFDataSync_stdlib(b *testing.B) {
removeFile()
b.ResetTimer()
for i := 0; i < b.N; i++ {
fdatasync_stdlib()
}
}
func BenchmarkFDataSync_x_sys(b *testing.B) {
removeFile()
b.ResetTimer()
for i := 0; i < b.N; i++ {
fdatasync_x_sys()
}
}
@komuw
Copy link
Author

komuw commented Oct 21, 2020

go test -timeout 10m -v -race -cover -bench=. -run=XXX ./...

BenchmarkFSync_stdlib-4       	       1	13182840400 ns/op.   // 13_182_840_400 ns/op
BenchmarkFSync_x_sys-4        	       1	13364355200 ns/op.   // 13_364_355_200 ns/op
BenchmarkFDataSync_stdlib-4   	       1	13715179700 ns/op.   // 13_715_179_700 ns/op
BenchmarkFDataSync_x_sys-4    	       1	13434866000 ns/op.   // 13_434_866_000 ns/op

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment