Add streaming read and write benchmarks

Run using

    ./main_benchmark.bash

Also, rewrite command line args handling
This commit is contained in:
Jakob Unterwurzacher 2015-09-06 11:42:01 +02:00
parent 58d1e24b7c
commit 5f4c9240ca
5 changed files with 190 additions and 18 deletions

View File

@ -68,7 +68,7 @@ func (f *File) Open(ctx context.Context, req *fuse.OpenRequest, resp *fuse.OpenR
func (f *File) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error { func (f *File) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error {
fmt.Printf("Read: o=%d l=%d\n", req.Offset, req.Size) cryptfs.Debug.Printf("Read: o=%d l=%d\n", req.Offset, req.Size)
// Read the backing ciphertext in one go // Read the backing ciphertext in one go
iblocks := f.crfs.SplitRange(uint64(req.Offset), uint64(req.Size)) iblocks := f.crfs.SplitRange(uint64(req.Offset), uint64(req.Size))

View File

@ -27,17 +27,17 @@ type nullTracer struct {}
func (nullTracer) Trace(op cluefs.FsOperTracer) {} func (nullTracer) Trace(op cluefs.FsOperTracer) {}
func NewFS(key [16]byte, backing string, useOpenssl bool) *FS { func NewFS(key [16]byte, backing string, useOpenssl bool) (*FS, error) {
var nt nullTracer var tracer nullTracer
clfs, err := cluefs.NewClueFS(backing, nt) clfs, err := cluefs.NewClueFS(backing, tracer)
if err != nil { if err != nil {
panic(err) return nil, err
} }
return &FS { return &FS {
CryptFS: cryptfs.NewCryptFS(key, useOpenssl), CryptFS: cryptfs.NewCryptFS(key, useOpenssl),
ClueFS: clfs, ClueFS: clfs,
backing: backing, backing: backing,
} }, nil
} }
func (fs *FS) Root() (fusefs.Node, error) { func (fs *FS) Root() (fusefs.Node, error) {

41
main.go
View File

@ -1,29 +1,46 @@
package main package main
import ( import (
"path/filepath"
"flag"
"os"
"fmt"
"github.com/rfjakob/gocryptfs/frontend"
"bazil.org/fuse" "bazil.org/fuse"
fusefs "bazil.org/fuse/fs" fusefs "bazil.org/fuse/fs"
"fmt"
"github.com/rfjakob/cluefs/lib/cluefs"
"github.com/rfjakob/gocryptfs/frontend"
"os"
) )
const ( const (
PROGRAM_NAME = "gocryptfs" PROGRAM_NAME = "gocryptfs"
USE_OPENSSL = true USE_OPENSSL = true
ERREXIT_USAGE = 1
ERREXIT_NEWFS = 2
ERREXIT_MOUNT = 3
ERREXIT_SERVE = 4
ERREXIT_MOUNT2 = 5
) )
func main() { func main() {
// Parse command line arguments // Parse command line arguments
conf, err := cluefs.ParseArguments() flag.Parse()
if err != nil { if flag.NArg() < 2 {
os.Exit(1) fmt.Printf("NArg=%d\n", flag.NArg())
fmt.Printf("usage: %s CIPHERDIR MOUNTPOINT\n", PROGRAM_NAME)
os.Exit(ERREXIT_USAGE)
} }
cipherdir, _ := filepath.Abs(flag.Arg(0))
mountpoint, err := filepath.Abs(flag.Arg(1))
// Create the file system object // Create the file system object
var key [16]byte var key [16]byte
cfs := frontend.NewFS(key, conf.GetShadowDir(), USE_OPENSSL) cfs, err := frontend.NewFS(key, cipherdir, USE_OPENSSL)
if err != nil {
fmt.Println(err)
os.Exit(ERREXIT_NEWFS)
}
// Mount the file system // Mount the file system
mountOpts := []fuse.MountOption{ mountOpts := []fuse.MountOption{
@ -33,24 +50,24 @@ func main() {
fuse.LocalVolume(), fuse.LocalVolume(),
fuse.MaxReadahead(1024*1024), fuse.MaxReadahead(1024*1024),
} }
conn, err := fuse.Mount(conf.GetMountPoint(), mountOpts...) conn, err := fuse.Mount(mountpoint, mountOpts...)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
os.Exit(1) os.Exit(ERREXIT_MOUNT)
} }
defer conn.Close() defer conn.Close()
// Start serving requests // Start serving requests
if err = fusefs.Serve(conn, cfs); err != nil { if err = fusefs.Serve(conn, cfs); err != nil {
fmt.Println(err) fmt.Println(err)
os.Exit(1) os.Exit(ERREXIT_SERVE)
} }
// Check for errors when mounting the file system // Check for errors when mounting the file system
<-conn.Ready <-conn.Ready
if err = conn.MountError; err != nil { if err = conn.MountError; err != nil {
fmt.Println(err) fmt.Println(err)
os.Exit(1) os.Exit(ERREXIT_MOUNT2)
} }
// We are done // We are done

6
main_benchmark.bash Executable file
View File

@ -0,0 +1,6 @@
#!/bin/bash
set -eux
go build
go test -bench=.

149
main_test.go Normal file
View File

@ -0,0 +1,149 @@
package main
import (
"io"
"fmt"
"time"
"testing"
"os"
"os/exec"
"io/ioutil"
"crypto/md5"
"encoding/hex"
)
const tmpDir = "test_tmp_dir/"
const plainDir = tmpDir + "plain/"
const cipherDir = tmpDir + "cipher/"
func TestMain(m *testing.M) {
fu := exec.Command("fusermount", "-u", plainDir)
fu.Stdout = os.Stdout
fu.Stderr = os.Stderr
fu.Run()
os.RemoveAll(tmpDir)
err := os.MkdirAll(plainDir, 0777)
if err != nil {
panic("Could not create plainDir")
}
err = os.MkdirAll(cipherDir, 0777)
if err != nil {
panic("Could not create cipherDir")
}
c := exec.Command("./gocryptfs", cipherDir, plainDir)
c.Stdout = os.Stdout
c.Stderr = os.Stderr
go c.Run()
time.Sleep(3 * time.Second)
r := m.Run()
fu.Run()
os.Exit(r)
}
func testWriteN(t *testing.T, fn string, n int, hashWant string) {
file, err := os.Create(plainDir + fn)
if err != nil {
t.FailNow()
}
d := make([]byte, n)
written, err := file.Write(d)
if err != nil || written != len(d) {
fmt.Printf("err=\"%s\", written=%d\n", err, written)
t.Fail()
}
file.Close()
buf, err := ioutil.ReadFile(plainDir + fn)
if err != nil {
t.Fail()
}
rawHash := md5.Sum(buf)
hashActual := hex.EncodeToString(rawHash[:])
if hashActual != hashWant {
fmt.Printf("hashWant=%s hashActual=%s\n", hashWant, hashActual)
t.Fail()
}
}
func TestWrite10(t *testing.T) {
testWriteN(t, "10", 10, "a63c90cc3684ad8b0a2176a6a8fe9005")
}
func TestWrite100(t *testing.T) {
testWriteN(t, "100", 100, "6d0bb00954ceb7fbee436bb55a8397a9")
}
func TestWrite1M(t *testing.T) {
testWriteN(t, "1M", 1024*1024, "b6d81b360a5672d80c27430f39153e2c")
}
func TestWrite1Mx100(t *testing.T) {
testWriteN(t, "1Mx100", 1024*1024, "b6d81b360a5672d80c27430f39153e2c")
// Read and check 100 times to catch race conditions
var i int
for i = 0; i < 100; i++ {
buf, err := ioutil.ReadFile(plainDir + "1M")
if err != nil {
t.Fail()
}
rawHash := md5.Sum(buf)
hashActual := hex.EncodeToString(rawHash[:])
if hashActual != "b6d81b360a5672d80c27430f39153e2c" {
fmt.Printf("Read corruption in loop # %d\n", i)
t.FailNow()
} else {
//fmt.Print(".")
}
}
}
func BenchmarkStreamWrite(t *testing.B) {
buf := make([]byte, 1024*1024)
t.SetBytes(int64(len(buf)))
file, err := os.Create(plainDir + "BenchmarkWrite")
if err != nil {
t.FailNow()
}
t.ResetTimer()
var i int
for i = 0; i < t.N; i++ {
written, err := file.Write(buf)
if err != nil {
fmt.Printf("err=\"%s\", written=%d\n", err.Error(), written)
t.FailNow()
}
}
}
func BenchmarkStreamRead(t *testing.B) {
buf := make([]byte, 1024*1024)
t.SetBytes(int64(len(buf)))
file, err := os.Open(plainDir + "BenchmarkWrite")
if err != nil {
t.FailNow()
}
t.ResetTimer()
var i int
for i = 0; i < t.N; i++ {
_, err := file.Read(buf)
if err == io.EOF {
fmt.Printf("Test file too small\n")
t.SkipNow()
} else if err != nil {
fmt.Println(err)
t.FailNow()
}
}
}