Add streaming read and write benchmarks
Run using ./main_benchmark.bash Also, rewrite command line args handling
This commit is contained in:
parent
58d1e24b7c
commit
5f4c9240ca
@ -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))
|
||||||
|
@ -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
41
main.go
@ -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
6
main_benchmark.bash
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
go build
|
||||||
|
go test -bench=.
|
149
main_test.go
Normal file
149
main_test.go
Normal 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user