From 943e80e26c82d56753b4a96e6a27d05c3bdea52e Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Wed, 21 Oct 2015 17:00:09 +0200 Subject: [PATCH] Make benchmarks more realistic --- lib/db/benchmark_test.go | 199 +++++++++++++++++++++++++++++++++++++++ lib/db/set_test.go | 187 ------------------------------------ 2 files changed, 199 insertions(+), 187 deletions(-) create mode 100644 lib/db/benchmark_test.go diff --git a/lib/db/benchmark_test.go b/lib/db/benchmark_test.go new file mode 100644 index 00000000..777b042a --- /dev/null +++ b/lib/db/benchmark_test.go @@ -0,0 +1,199 @@ +// Copyright (C) 2015 The Syncthing Authors. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at http://mozilla.org/MPL/2.0/. + +package db_test + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "testing" + + "github.com/syncthing/syncthing/lib/db" + "github.com/syncthing/syncthing/lib/protocol" + "github.com/syndtr/goleveldb/leveldb" + "github.com/syndtr/goleveldb/leveldb/opt" +) + +var files, oneFile, firstHalf, secondHalf []protocol.FileInfo +var fs *db.FileSet + +func init() { + for i := 0; i < 1000; i++ { + files = append(files, protocol.FileInfo{ + Name: fmt.Sprintf("file%d", i), + Version: protocol.Vector{{ID: myID, Value: 1000}}, + Blocks: genBlocks(i), + }) + } + + middle := len(files) / 2 + firstHalf = files[:middle] + secondHalf = files[middle:] + oneFile = firstHalf[middle-1 : middle] + + ldb, _ := tempDB() + fs = db.NewFileSet("test", ldb) + fs.Replace(remoteDevice0, files) + fs.Replace(protocol.LocalDeviceID, firstHalf) +} + +func genBlocks(n int) []protocol.BlockInfo { + b := make([]protocol.BlockInfo, n) + for i := range b { + h := make([]byte, 32) + for j := range h { + h[j] = byte(i + j) + } + b[i].Size = int32(i) + b[i].Hash = h + } + return b +} + +func tempDB() (*leveldb.DB, string) { + dir, err := ioutil.TempDir("", "syncthing") + if err != nil { + panic(err) + } + db, err := leveldb.OpenFile(filepath.Join(dir, "db"), &opt.Options{OpenFilesCacheCapacity: 100}) + if err != nil { + panic(err) + } + return db, dir +} + +func BenchmarkReplaceAll(b *testing.B) { + ldb, dir := tempDB() + defer func() { + ldb.Close() + os.RemoveAll(dir) + }() + + b.ResetTimer() + for i := 0; i < b.N; i++ { + m := db.NewFileSet("test", ldb) + m.Replace(protocol.LocalDeviceID, files) + } + + b.ReportAllocs() +} + +func BenchmarkUpdateOneChanged(b *testing.B) { + changed := make([]protocol.FileInfo, 1) + changed[0] = oneFile[0] + changed[0].Version = changed[0].Version.Update(myID) + changed[0].Blocks = genBlocks(len(changed[0].Blocks)) + + for i := 0; i < b.N; i++ { + if i%1 == 0 { + fs.Update(protocol.LocalDeviceID, changed) + } else { + fs.Update(protocol.LocalDeviceID, oneFile) + } + } + + b.ReportAllocs() +} + +func BenchmarkUpdateOneUnchanged(b *testing.B) { + for i := 0; i < b.N; i++ { + fs.Update(protocol.LocalDeviceID, oneFile) + } + + b.ReportAllocs() +} + +func BenchmarkNeedHalf(b *testing.B) { + for i := 0; i < b.N; i++ { + count := 0 + fs.WithNeed(protocol.LocalDeviceID, func(fi db.FileIntf) bool { + count++ + return true + }) + if count != len(secondHalf) { + b.Errorf("wrong length %d != %d", count, len(secondHalf)) + } + } + + b.ReportAllocs() +} + +func BenchmarkHave(b *testing.B) { + for i := 0; i < b.N; i++ { + count := 0 + fs.WithHave(protocol.LocalDeviceID, func(fi db.FileIntf) bool { + count++ + return true + }) + if count != len(firstHalf) { + b.Errorf("wrong length %d != %d", count, len(firstHalf)) + } + } + + b.ReportAllocs() +} + +func BenchmarkGlobal(b *testing.B) { + for i := 0; i < b.N; i++ { + count := 0 + fs.WithGlobal(func(fi db.FileIntf) bool { + count++ + return true + }) + if count != len(files) { + b.Errorf("wrong length %d != %d", count, len(files)) + } + } + + b.ReportAllocs() +} + +func BenchmarkNeedHalfTruncated(b *testing.B) { + for i := 0; i < b.N; i++ { + count := 0 + fs.WithNeedTruncated(protocol.LocalDeviceID, func(fi db.FileIntf) bool { + count++ + return true + }) + if count != len(secondHalf) { + b.Errorf("wrong length %d != %d", count, len(secondHalf)) + } + } + + b.ReportAllocs() +} + +func BenchmarkHaveTruncated(b *testing.B) { + for i := 0; i < b.N; i++ { + count := 0 + fs.WithHaveTruncated(protocol.LocalDeviceID, func(fi db.FileIntf) bool { + count++ + return true + }) + if count != len(firstHalf) { + b.Errorf("wrong length %d != %d", count, len(firstHalf)) + } + } + + b.ReportAllocs() +} + +func BenchmarkGlobalTruncated(b *testing.B) { + for i := 0; i < b.N; i++ { + count := 0 + fs.WithGlobalTruncated(func(fi db.FileIntf) bool { + count++ + return true + }) + if count != len(files) { + b.Errorf("wrong length %d != %d", count, len(files)) + } + } + + b.ReportAllocs() +} diff --git a/lib/db/set_test.go b/lib/db/set_test.go index 64e12603..45f5837a 100644 --- a/lib/db/set_test.go +++ b/lib/db/set_test.go @@ -28,19 +28,6 @@ func init() { const myID = 1 -func genBlocks(n int) []protocol.BlockInfo { - b := make([]protocol.BlockInfo, n) - for i := range b { - h := make([]byte, 32) - for j := range h { - h[j] = byte(i + j) - } - b[i].Size = int32(i) - b[i].Hash = h - } - return b -} - func globalList(s *db.FileSet) []protocol.FileInfo { var fs []protocol.FileInfo s.WithGlobal(func(fi db.FileIntf) bool { @@ -417,180 +404,6 @@ func TestInvalidAvailability(t *testing.T) { t.Error("Incorrect availability for 'none':", av) } } -func Benchmark10kReplace(b *testing.B) { - ldb, err := leveldb.Open(storage.NewMemStorage(), nil) - if err != nil { - b.Fatal(err) - } - - var local []protocol.FileInfo - for i := 0; i < 10000; i++ { - local = append(local, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{ID: myID, Value: 1000}}}) - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - m := db.NewFileSet("test", ldb) - m.Replace(protocol.LocalDeviceID, local) - } -} - -func Benchmark10kUpdateChg(b *testing.B) { - var remote []protocol.FileInfo - for i := 0; i < 10000; i++ { - remote = append(remote, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{ID: myID, Value: 1000}}}) - } - - ldb, err := leveldb.Open(storage.NewMemStorage(), nil) - if err != nil { - b.Fatal(err) - } - - m := db.NewFileSet("test", ldb) - m.Replace(remoteDevice0, remote) - - var local []protocol.FileInfo - for i := 0; i < 10000; i++ { - local = append(local, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{ID: myID, Value: 1000}}}) - } - - m.Replace(protocol.LocalDeviceID, local) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - b.StopTimer() - for j := range local { - local[j].Version = local[j].Version.Update(myID) - } - b.StartTimer() - m.Update(protocol.LocalDeviceID, local) - } -} - -func Benchmark10kUpdateSme(b *testing.B) { - var remote []protocol.FileInfo - for i := 0; i < 10000; i++ { - remote = append(remote, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{ID: myID, Value: 1000}}}) - } - - ldb, err := leveldb.Open(storage.NewMemStorage(), nil) - if err != nil { - b.Fatal(err) - } - m := db.NewFileSet("test", ldb) - m.Replace(remoteDevice0, remote) - - var local []protocol.FileInfo - for i := 0; i < 10000; i++ { - local = append(local, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{ID: myID, Value: 1000}}}) - } - - m.Replace(protocol.LocalDeviceID, local) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - m.Update(protocol.LocalDeviceID, local) - } -} - -func Benchmark10kNeed2k(b *testing.B) { - var remote []protocol.FileInfo - for i := 0; i < 10000; i++ { - remote = append(remote, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{ID: myID, Value: 1000}}}) - } - - ldb, err := leveldb.Open(storage.NewMemStorage(), nil) - if err != nil { - b.Fatal(err) - } - - m := db.NewFileSet("test", ldb) - m.Replace(remoteDevice0, remote) - - var local []protocol.FileInfo - for i := 0; i < 8000; i++ { - local = append(local, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{ID: myID, Value: 1000}}}) - } - for i := 8000; i < 10000; i++ { - local = append(local, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{1, 980}}}) - } - - m.Replace(protocol.LocalDeviceID, local) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - fs := needList(m, protocol.LocalDeviceID) - if l := len(fs); l != 2000 { - b.Errorf("wrong length %d != 2k", l) - } - } -} - -func Benchmark10kHaveFullList(b *testing.B) { - var remote []protocol.FileInfo - for i := 0; i < 10000; i++ { - remote = append(remote, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{ID: myID, Value: 1000}}}) - } - - ldb, err := leveldb.Open(storage.NewMemStorage(), nil) - if err != nil { - b.Fatal(err) - } - - m := db.NewFileSet("test", ldb) - m.Replace(remoteDevice0, remote) - - var local []protocol.FileInfo - for i := 0; i < 2000; i++ { - local = append(local, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{ID: myID, Value: 1000}}}) - } - for i := 2000; i < 10000; i++ { - local = append(local, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{1, 980}}}) - } - - m.Replace(protocol.LocalDeviceID, local) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - fs := haveList(m, protocol.LocalDeviceID) - if l := len(fs); l != 10000 { - b.Errorf("wrong length %d != 10k", l) - } - } -} - -func Benchmark10kGlobal(b *testing.B) { - var remote []protocol.FileInfo - for i := 0; i < 10000; i++ { - remote = append(remote, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{ID: myID, Value: 1000}}}) - } - - ldb, err := leveldb.Open(storage.NewMemStorage(), nil) - if err != nil { - b.Fatal(err) - } - - m := db.NewFileSet("test", ldb) - m.Replace(remoteDevice0, remote) - - var local []protocol.FileInfo - for i := 0; i < 2000; i++ { - local = append(local, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{ID: myID, Value: 1000}}}) - } - for i := 2000; i < 10000; i++ { - local = append(local, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{1, 980}}}) - } - - m.Replace(protocol.LocalDeviceID, local) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - fs := globalList(m) - if l := len(fs); l != 10000 { - b.Errorf("wrong length %d != 10k", l) - } - } -} func TestGlobalReset(t *testing.T) { ldb, err := leveldb.Open(storage.NewMemStorage(), nil)