From 84920d11ddb7480758788f6cbb7718d96eda95ae Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Tue, 31 Aug 2021 12:43:16 +0300 Subject: [PATCH] Add vectored read to readbenchfs You can now run `./readbenchfs --mount_point dir --vectored` and then `dd if=dir/test of=/dev/null iflag=direct bs=1M status=progress` to test vectored read speed. Results from my laptop (Linux 5.10): 1 core (GOMAXPROCS=1): - Before vectored read patch: 2.1 GB/s - Non-vectored read after vectored read patch: 2.1 GB/s - Vectored read: 2.8 GB/s All cores: - Before vectored read patch: 3.0 GB/s - Non-vectored read after vectored read patch: 3.3 GB/s - Vectored read: 5.9 GB/s --- samples/mount_readbenchfs/mount.go | 6 ++++-- samples/readbenchfs/readbenchfs.go | 19 +++++++++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/samples/mount_readbenchfs/mount.go b/samples/mount_readbenchfs/mount.go index 56bb33d..6fa37c7 100644 --- a/samples/mount_readbenchfs/mount.go +++ b/samples/mount_readbenchfs/mount.go @@ -14,6 +14,7 @@ import ( var fMountPoint = flag.String("mount_point", "", "Path to mount point.") var fReadOnly = flag.Bool("read_only", false, "Mount in read-only mode.") +var fVectored = flag.Bool("vectored", false, "Use vectored read.") var fDebug = flag.Bool("debug", false, "Enable debug logging.") var fPprof = flag.Int("pprof", 0, "Enable pprof profiling on the specified port.") @@ -26,7 +27,7 @@ func main() { }() } - server, err := readbenchfs.NewReadBenchServer() + server, err := readbenchfs.NewReadBenchServer(*fVectored) if err != nil { log.Fatalf("makeFS: %v", err) } @@ -37,7 +38,8 @@ func main() { } cfg := &fuse.MountConfig{ - ReadOnly: *fReadOnly, + ReadOnly: *fReadOnly, + UseVectoredRead: *fVectored, } if *fDebug { diff --git a/samples/readbenchfs/readbenchfs.go b/samples/readbenchfs/readbenchfs.go index d4f0ee1..61b18df 100644 --- a/samples/readbenchfs/readbenchfs.go +++ b/samples/readbenchfs/readbenchfs.go @@ -27,7 +27,8 @@ import ( type readBenchFS struct { fuseutil.NotImplementedFileSystem - buf []byte + buf []byte + useVectoredRead bool } // 1 TB @@ -35,14 +36,13 @@ const fileSize = 1024 * 1024 * 1024 * 1024 var _ fuseutil.FileSystem = &readBenchFS{} -// Create a file system that mirrors an existing physical path, in a readonly mode - -func NewReadBenchServer() (server fuse.Server, err error) { +func NewReadBenchServer(useVectoredRead bool) (server fuse.Server, err error) { // 1 GB of random data to exceed CPU cache buf := make([]byte, 1024*1024*1024) rand.Read(buf) server = fuseutil.NewFileSystemServer(&readBenchFS{ - buf: buf, + buf: buf, + useVectoredRead: useVectoredRead, }) return } @@ -123,7 +123,7 @@ func (fs *readBenchFS) ReadFile(ctx context.Context, op *fuseops.ReadFileOp) err if op.Offset > fileSize { return io.EOF } - end := op.Offset + int64(len(op.Dst)) + end := op.Offset + op.Size if end > fileSize { end = fileSize } @@ -134,10 +134,13 @@ func (fs *readBenchFS) ReadFile(ctx context.Context, op *fuseops.ReadFileOp) err if e-s > end-pos { e = s + end - pos } - copy(op.Dst[pos-op.Offset:], fs.buf[s:]) + if fs.useVectoredRead { + op.Data = append(op.Data, fs.buf[s:e]) + } else { + copy(op.Dst[pos-op.Offset:], fs.buf[s:]) + } pos = op.Offset + e } - //op.Data = [][]byte{ contents[op.Offset : end] } op.BytesRead = int(end - op.Offset) return nil }