mirror of
https://github.com/restic/restic.git
synced 2024-08-24 13:17:23 +02:00
269 lines
5.3 KiB
Go
269 lines
5.3 KiB
Go
package bench_test
|
|
|
|
import (
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"path"
|
|
"testing"
|
|
|
|
"bazil.org/fuse"
|
|
"bazil.org/fuse/fs"
|
|
"bazil.org/fuse/fs/fstestutil"
|
|
"golang.org/x/net/context"
|
|
)
|
|
|
|
type benchConfig struct {
|
|
directIO bool
|
|
}
|
|
|
|
type benchFS struct {
|
|
conf *benchConfig
|
|
}
|
|
|
|
var _ = fs.FS(benchFS{})
|
|
|
|
func (f benchFS) Root() (fs.Node, error) {
|
|
return benchDir{conf: f.conf}, nil
|
|
}
|
|
|
|
type benchDir struct {
|
|
conf *benchConfig
|
|
}
|
|
|
|
var _ = fs.Node(benchDir{})
|
|
var _ = fs.NodeStringLookuper(benchDir{})
|
|
var _ = fs.Handle(benchDir{})
|
|
var _ = fs.HandleReadDirAller(benchDir{})
|
|
|
|
func (benchDir) Attr(ctx context.Context, a *fuse.Attr) error {
|
|
a.Inode = 1
|
|
a.Mode = os.ModeDir | 0555
|
|
return nil
|
|
}
|
|
|
|
func (d benchDir) Lookup(ctx context.Context, name string) (fs.Node, error) {
|
|
if name == "bench" {
|
|
return benchFile{conf: d.conf}, nil
|
|
}
|
|
return nil, fuse.ENOENT
|
|
}
|
|
|
|
func (benchDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
|
|
l := []fuse.Dirent{
|
|
{Inode: 2, Name: "bench", Type: fuse.DT_File},
|
|
}
|
|
return l, nil
|
|
}
|
|
|
|
type benchFile struct {
|
|
conf *benchConfig
|
|
}
|
|
|
|
var _ = fs.Node(benchFile{})
|
|
var _ = fs.NodeOpener(benchFile{})
|
|
var _ = fs.NodeFsyncer(benchFile{})
|
|
var _ = fs.Handle(benchFile{})
|
|
var _ = fs.HandleReader(benchFile{})
|
|
var _ = fs.HandleWriter(benchFile{})
|
|
|
|
func (benchFile) Attr(ctx context.Context, a *fuse.Attr) error {
|
|
a.Inode = 2
|
|
a.Mode = 0644
|
|
a.Size = 9999999999999999
|
|
return nil
|
|
}
|
|
|
|
func (f benchFile) Open(ctx context.Context, req *fuse.OpenRequest, resp *fuse.OpenResponse) (fs.Handle, error) {
|
|
if f.conf.directIO {
|
|
resp.Flags |= fuse.OpenDirectIO
|
|
}
|
|
// TODO configurable?
|
|
resp.Flags |= fuse.OpenKeepCache
|
|
return f, nil
|
|
}
|
|
|
|
func (benchFile) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error {
|
|
resp.Data = resp.Data[:cap(resp.Data)]
|
|
return nil
|
|
}
|
|
|
|
func (benchFile) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) error {
|
|
resp.Size = len(req.Data)
|
|
return nil
|
|
}
|
|
|
|
func (benchFile) Fsync(ctx context.Context, req *fuse.FsyncRequest) error {
|
|
return nil
|
|
}
|
|
|
|
func benchmark(b *testing.B, fn func(b *testing.B, mnt string), conf *benchConfig) {
|
|
filesys := benchFS{
|
|
conf: conf,
|
|
}
|
|
mnt, err := fstestutil.Mounted(filesys, nil,
|
|
fuse.MaxReadahead(64*1024*1024),
|
|
fuse.AsyncRead(),
|
|
fuse.WritebackCache(),
|
|
)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
defer mnt.Close()
|
|
|
|
fn(b, mnt.Dir)
|
|
}
|
|
|
|
type zero struct{}
|
|
|
|
func (zero) Read(p []byte) (n int, err error) {
|
|
return len(p), nil
|
|
}
|
|
|
|
var Zero io.Reader = zero{}
|
|
|
|
func doWrites(size int64) func(b *testing.B, mnt string) {
|
|
return func(b *testing.B, mnt string) {
|
|
p := path.Join(mnt, "bench")
|
|
|
|
f, err := os.Create(p)
|
|
if err != nil {
|
|
b.Fatalf("create: %v", err)
|
|
}
|
|
defer f.Close()
|
|
|
|
b.ResetTimer()
|
|
b.SetBytes(size)
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
_, err = io.CopyN(f, Zero, size)
|
|
if err != nil {
|
|
b.Fatalf("write: %v", err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkWrite100(b *testing.B) {
|
|
benchmark(b, doWrites(100), &benchConfig{})
|
|
}
|
|
|
|
func BenchmarkWrite10MB(b *testing.B) {
|
|
benchmark(b, doWrites(10*1024*1024), &benchConfig{})
|
|
}
|
|
|
|
func BenchmarkWrite100MB(b *testing.B) {
|
|
benchmark(b, doWrites(100*1024*1024), &benchConfig{})
|
|
}
|
|
|
|
func BenchmarkDirectWrite100(b *testing.B) {
|
|
benchmark(b, doWrites(100), &benchConfig{
|
|
directIO: true,
|
|
})
|
|
}
|
|
|
|
func BenchmarkDirectWrite10MB(b *testing.B) {
|
|
benchmark(b, doWrites(10*1024*1024), &benchConfig{
|
|
directIO: true,
|
|
})
|
|
}
|
|
|
|
func BenchmarkDirectWrite100MB(b *testing.B) {
|
|
benchmark(b, doWrites(100*1024*1024), &benchConfig{
|
|
directIO: true,
|
|
})
|
|
}
|
|
|
|
func doWritesSync(size int64) func(b *testing.B, mnt string) {
|
|
return func(b *testing.B, mnt string) {
|
|
p := path.Join(mnt, "bench")
|
|
|
|
f, err := os.Create(p)
|
|
if err != nil {
|
|
b.Fatalf("create: %v", err)
|
|
}
|
|
defer f.Close()
|
|
|
|
b.ResetTimer()
|
|
b.SetBytes(size)
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
_, err = io.CopyN(f, Zero, size)
|
|
if err != nil {
|
|
b.Fatalf("write: %v", err)
|
|
}
|
|
|
|
if err := f.Sync(); err != nil {
|
|
b.Fatalf("sync: %v", err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkWriteSync100(b *testing.B) {
|
|
benchmark(b, doWritesSync(100), &benchConfig{})
|
|
}
|
|
|
|
func BenchmarkWriteSync10MB(b *testing.B) {
|
|
benchmark(b, doWritesSync(10*1024*1024), &benchConfig{})
|
|
}
|
|
|
|
func BenchmarkWriteSync100MB(b *testing.B) {
|
|
benchmark(b, doWritesSync(100*1024*1024), &benchConfig{})
|
|
}
|
|
|
|
func doReads(size int64) func(b *testing.B, mnt string) {
|
|
return func(b *testing.B, mnt string) {
|
|
p := path.Join(mnt, "bench")
|
|
|
|
f, err := os.Open(p)
|
|
if err != nil {
|
|
b.Fatalf("close: %v", err)
|
|
}
|
|
defer f.Close()
|
|
|
|
b.ResetTimer()
|
|
b.SetBytes(size)
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
n, err := io.CopyN(ioutil.Discard, f, size)
|
|
if err != nil {
|
|
b.Fatalf("read: %v", err)
|
|
}
|
|
if n != size {
|
|
b.Errorf("unexpected size: %d != %d", n, size)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkRead100(b *testing.B) {
|
|
benchmark(b, doReads(100), &benchConfig{})
|
|
}
|
|
|
|
func BenchmarkRead10MB(b *testing.B) {
|
|
benchmark(b, doReads(10*1024*1024), &benchConfig{})
|
|
}
|
|
|
|
func BenchmarkRead100MB(b *testing.B) {
|
|
benchmark(b, doReads(100*1024*1024), &benchConfig{})
|
|
}
|
|
|
|
func BenchmarkDirectRead100(b *testing.B) {
|
|
benchmark(b, doReads(100), &benchConfig{
|
|
directIO: true,
|
|
})
|
|
}
|
|
|
|
func BenchmarkDirectRead10MB(b *testing.B) {
|
|
benchmark(b, doReads(10*1024*1024), &benchConfig{
|
|
directIO: true,
|
|
})
|
|
}
|
|
|
|
func BenchmarkDirectRead100MB(b *testing.B) {
|
|
benchmark(b, doReads(100*1024*1024), &benchConfig{
|
|
directIO: true,
|
|
})
|
|
}
|