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
geesefs-0-31-3
Vitaliy Filippov 2021-08-31 12:43:16 +03:00 committed by Michael Stapelberg
parent c818f6216b
commit 84920d11dd
2 changed files with 15 additions and 10 deletions

View File

@ -14,6 +14,7 @@ import (
var fMountPoint = flag.String("mount_point", "", "Path to mount point.") var fMountPoint = flag.String("mount_point", "", "Path to mount point.")
var fReadOnly = flag.Bool("read_only", false, "Mount in read-only mode.") 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 fDebug = flag.Bool("debug", false, "Enable debug logging.")
var fPprof = flag.Int("pprof", 0, "Enable pprof profiling on the specified port.") 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 { if err != nil {
log.Fatalf("makeFS: %v", err) log.Fatalf("makeFS: %v", err)
} }
@ -37,7 +38,8 @@ func main() {
} }
cfg := &fuse.MountConfig{ cfg := &fuse.MountConfig{
ReadOnly: *fReadOnly, ReadOnly: *fReadOnly,
UseVectoredRead: *fVectored,
} }
if *fDebug { if *fDebug {

View File

@ -27,7 +27,8 @@ import (
type readBenchFS struct { type readBenchFS struct {
fuseutil.NotImplementedFileSystem fuseutil.NotImplementedFileSystem
buf []byte buf []byte
useVectoredRead bool
} }
// 1 TB // 1 TB
@ -35,14 +36,13 @@ const fileSize = 1024 * 1024 * 1024 * 1024
var _ fuseutil.FileSystem = &readBenchFS{} var _ fuseutil.FileSystem = &readBenchFS{}
// Create a file system that mirrors an existing physical path, in a readonly mode func NewReadBenchServer(useVectoredRead bool) (server fuse.Server, err error) {
func NewReadBenchServer() (server fuse.Server, err error) {
// 1 GB of random data to exceed CPU cache // 1 GB of random data to exceed CPU cache
buf := make([]byte, 1024*1024*1024) buf := make([]byte, 1024*1024*1024)
rand.Read(buf) rand.Read(buf)
server = fuseutil.NewFileSystemServer(&readBenchFS{ server = fuseutil.NewFileSystemServer(&readBenchFS{
buf: buf, buf: buf,
useVectoredRead: useVectoredRead,
}) })
return return
} }
@ -123,7 +123,7 @@ func (fs *readBenchFS) ReadFile(ctx context.Context, op *fuseops.ReadFileOp) err
if op.Offset > fileSize { if op.Offset > fileSize {
return io.EOF return io.EOF
} }
end := op.Offset + int64(len(op.Dst)) end := op.Offset + op.Size
if end > fileSize { if end > fileSize {
end = fileSize end = fileSize
} }
@ -134,10 +134,13 @@ func (fs *readBenchFS) ReadFile(ctx context.Context, op *fuseops.ReadFileOp) err
if e-s > end-pos { if e-s > end-pos {
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 pos = op.Offset + e
} }
//op.Data = [][]byte{ contents[op.Offset : end] }
op.BytesRead = int(end - op.Offset) op.BytesRead = int(end - op.Offset)
return nil return nil
} }