From 6a451071932b97807bc4070ba83d130d4d357139 Mon Sep 17 00:00:00 2001 From: Leo Balduf Date: Thu, 11 Aug 2016 20:02:10 -0400 Subject: [PATCH] make benchmarks parallel, fix memory benchmarks --- storage/memory/peer_store_test.go | 56 +++++----- storage/storage_bench.go | 168 +++++++++++++++++------------- 2 files changed, 129 insertions(+), 95 deletions(-) diff --git a/storage/memory/peer_store_test.go b/storage/memory/peer_store_test.go index df3a0c1..d85be46 100644 --- a/storage/memory/peer_store_test.go +++ b/storage/memory/peer_store_test.go @@ -6,27 +6,35 @@ import ( s "github.com/jzelinskie/trakr/storage" ) -func BenchmarkPut(b *testing.B) { s.Put(b, &peerStore{}) } -func BenchmarkPut1k(b *testing.B) { s.Put1k(b, &peerStore{}) } -func BenchmarkPut1kInfohash(b *testing.B) { s.Put1kInfohash(b, &peerStore{}) } -func BenchmarkPut1kInfohash1k(b *testing.B) { s.Put1kInfohash1k(b, &peerStore{}) } -func BenchmarkPutDelete(b *testing.B) { s.PutDelete(b, &peerStore{}) } -func BenchmarkPutDelete1k(b *testing.B) { s.PutDelete1k(b, &peerStore{}) } -func BenchmarkPutDelete1kInfohash(b *testing.B) { s.PutDelete1kInfohash(b, &peerStore{}) } -func BenchmarkPutDelete1kInfohash1k(b *testing.B) { s.PutDelete1kInfohash1k(b, &peerStore{}) } -func BenchmarkDeleteNonexist(b *testing.B) { s.DeleteNonexist(b, &peerStore{}) } -func BenchmarkDeleteNonexist1k(b *testing.B) { s.DeleteNonexist1k(b, &peerStore{}) } -func BenchmarkDeleteNonexist1kInfohash(b *testing.B) { s.DeleteNonexist1kInfohash(b, &peerStore{}) } -func BenchmarkDeleteNonexist1kInfohash1k(b *testing.B) { s.DeleteNonexist1kInfohash1k(b, &peerStore{}) } -func BenchmarkGradDelete(b *testing.B) { s.GradDelete(b, &peerStore{}) } -func BenchmarkGradDelete1k(b *testing.B) { s.GradDelete1k(b, &peerStore{}) } -func BenchmarkGradDelete1kInfohash(b *testing.B) { s.GradDelete1kInfohash(b, &peerStore{}) } -func BenchmarkGradDelete1kInfohash1k(b *testing.B) { s.GradDelete1kInfohash1k(b, &peerStore{}) } -func BenchmarkGradNonexist(b *testing.B) { s.GradNonexist(b, &peerStore{}) } -func BenchmarkGradNonexist1k(b *testing.B) { s.GradNonexist1k(b, &peerStore{}) } -func BenchmarkGradNonexist1kInfohash(b *testing.B) { s.GradNonexist1kInfohash(b, &peerStore{}) } -func BenchmarkGradNonexist1kInfohash1k(b *testing.B) { s.GradNonexist1kInfohash1k(b, &peerStore{}) } -func BenchmarkAnnounceLeecher(b *testing.B) { s.AnnounceLeecher(b, &peerStore{}) } -func BenchmarkAnnounceLeecher1kInfohash(b *testing.B) { s.AnnounceLeecher1kInfohash(b, &peerStore{}) } -func BenchmarkAnnounceSeeder(b *testing.B) { s.AnnounceSeeder(b, &peerStore{}) } -func BenchmarkAnnounceSeeder1kInfohash(b *testing.B) { s.AnnounceSeeder1kInfohash(b, &peerStore{}) } +func createNew() s.PeerStore { + ps, err := New(Config{ShardCount: 1024}) + if err != nil { + panic(err) + } + return ps +} + +func BenchmarkPut(b *testing.B) { s.Put(b, createNew()) } +func BenchmarkPut1k(b *testing.B) { s.Put1k(b, createNew()) } +func BenchmarkPut1kInfohash(b *testing.B) { s.Put1kInfohash(b, createNew()) } +func BenchmarkPut1kInfohash1k(b *testing.B) { s.Put1kInfohash1k(b, createNew()) } +func BenchmarkPutDelete(b *testing.B) { s.PutDelete(b, createNew()) } +func BenchmarkPutDelete1k(b *testing.B) { s.PutDelete1k(b, createNew()) } +func BenchmarkPutDelete1kInfohash(b *testing.B) { s.PutDelete1kInfohash(b, createNew()) } +func BenchmarkPutDelete1kInfohash1k(b *testing.B) { s.PutDelete1kInfohash1k(b, createNew()) } +func BenchmarkDeleteNonexist(b *testing.B) { s.DeleteNonexist(b, createNew()) } +func BenchmarkDeleteNonexist1k(b *testing.B) { s.DeleteNonexist1k(b, createNew()) } +func BenchmarkDeleteNonexist1kInfohash(b *testing.B) { s.DeleteNonexist1kInfohash(b, createNew()) } +func BenchmarkDeleteNonexist1kInfohash1k(b *testing.B) { s.DeleteNonexist1kInfohash1k(b, createNew()) } +func BenchmarkPutGradDelete(b *testing.B) { s.PutGradDelete(b, createNew()) } +func BenchmarkPutGradDelete1k(b *testing.B) { s.PutGradDelete1k(b, createNew()) } +func BenchmarkPutGradDelete1kInfohash(b *testing.B) { s.PutGradDelete1kInfohash(b, createNew()) } +func BenchmarkPutGradDelete1kInfohash1k(b *testing.B) { s.PutGradDelete1kInfohash1k(b, createNew()) } +func BenchmarkGradNonexist(b *testing.B) { s.GradNonexist(b, createNew()) } +func BenchmarkGradNonexist1k(b *testing.B) { s.GradNonexist1k(b, createNew()) } +func BenchmarkGradNonexist1kInfohash(b *testing.B) { s.GradNonexist1kInfohash(b, createNew()) } +func BenchmarkGradNonexist1kInfohash1k(b *testing.B) { s.GradNonexist1kInfohash1k(b, createNew()) } +func BenchmarkAnnounceLeecher(b *testing.B) { s.AnnounceLeecher(b, createNew()) } +func BenchmarkAnnounceLeecher1kInfohash(b *testing.B) { s.AnnounceLeecher1kInfohash(b, createNew()) } +func BenchmarkAnnounceSeeder(b *testing.B) { s.AnnounceSeeder(b, createNew()) } +func BenchmarkAnnounceSeeder1kInfohash(b *testing.B) { s.AnnounceSeeder1kInfohash(b, createNew()) } diff --git a/storage/storage_bench.go b/storage/storage_bench.go index c76bd41..316a425 100644 --- a/storage/storage_bench.go +++ b/storage/storage_bench.go @@ -1,8 +1,10 @@ package storage import ( - "fmt" + "math/rand" "net" + "runtime" + "sync/atomic" "testing" "github.com/jzelinskie/trakr/bittorrent" @@ -14,25 +16,37 @@ type benchData struct { } func generateInfohashes() (a [1000]bittorrent.InfoHash) { - b := make([]byte, 2) + r := rand.New(rand.NewSource(0)) for i := range a { - b[0] = byte(i) - b[1] = byte(i >> 8) - a[i] = bittorrent.InfoHash([20]byte{b[0], b[1]}) + b := [20]byte{} + n, err := r.Read(b[:]) + if err != nil || n != 20 { + panic("unable to create random bytes") + } + a[i] = bittorrent.InfoHash(b) } return } func generatePeers() (a [1000]bittorrent.Peer) { - b := make([]byte, 2) + r := rand.New(rand.NewSource(0)) for i := range a { - b[0] = byte(i) - b[1] = byte(i >> 8) + ip := make([]byte, 4) + n, err := r.Read(ip) + if err != nil || n != 4 { + panic("unable to create random bytes") + } + id := [20]byte{} + n, err = r.Read(id[:]) + if err != nil || n != 20 { + panic("unable to create random bytes") + } + port := uint16(r.Uint32()) a[i] = bittorrent.Peer{ - ID: bittorrent.PeerID([20]byte{b[0], b[1]}), - IP: net.ParseIP(fmt.Sprintf("64.%d.%d.64", b[0], b[1])), - Port: uint16(i), + ID: bittorrent.PeerID(id), + IP: net.IP(ip), + Port: port, } } @@ -42,53 +56,67 @@ func generatePeers() (a [1000]bittorrent.Peer) { type executionFunc func(int, PeerStore, *benchData) error type setupFunc func(PeerStore, *benchData) error -func runBenchmark(b *testing.B, ps PeerStore, sf setupFunc, ef executionFunc) { +func runBenchmark(b *testing.B, ps PeerStore, parallel bool, sf setupFunc, ef executionFunc) { bd := &benchData{generateInfohashes(), generatePeers()} + spacing := int32(1000 / runtime.NumCPU()) if sf != nil { err := sf(ps, bd) if err != nil { b.Fatal(err) } } + offset := int32(0) + b.ResetTimer() - for i := 0; i < b.N; i++ { - err := ef(i, ps, bd) - if err != nil { - b.Fatal(err) + if parallel { + b.RunParallel(func(pb *testing.PB) { + i := int(atomic.AddInt32(&offset, spacing)) + for pb.Next() { + err := ef(i, ps, bd) + if err != nil { + b.Fatal(err) + } + i++ + } + }) + } else { + for i := 0; i < b.N; i++ { + err := ef(i, ps, bd) + if err != nil { + b.Fatal(err) + } } } b.StopTimer() } func Put(b *testing.B, ps PeerStore) { - runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { + runBenchmark(b, ps, true, nil, func(i int, ps PeerStore, bd *benchData) error { return ps.PutSeeder(bd.infohashes[0], bd.peers[0]) }) } func Put1k(b *testing.B, ps PeerStore) { - runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { + runBenchmark(b, ps, true, nil, func(i int, ps PeerStore, bd *benchData) error { return ps.PutSeeder(bd.infohashes[0], bd.peers[i%1000]) }) } func Put1kInfohash(b *testing.B, ps PeerStore) { - runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { + runBenchmark(b, ps, true, nil, func(i int, ps PeerStore, bd *benchData) error { return ps.PutSeeder(bd.infohashes[i%1000], bd.peers[0]) }) } func Put1kInfohash1k(b *testing.B, ps PeerStore) { - j := 0 - runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { - err := ps.PutSeeder(bd.infohashes[i%1000], bd.peers[j%1000]) - j += 3 + runBenchmark(b, ps, true, nil, func(i int, ps PeerStore, bd *benchData) error { + err := ps.PutSeeder(bd.infohashes[i%1000], bd.peers[(i*3)%1000]) return err }) } func PutDelete(b *testing.B, ps PeerStore) { - runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { + runBenchmark(b, ps, false, nil, func(i int, ps PeerStore, bd *benchData) error { err := ps.PutSeeder(bd.infohashes[0], bd.peers[0]) if err != nil { return err @@ -98,7 +126,7 @@ func PutDelete(b *testing.B, ps PeerStore) { } func PutDelete1k(b *testing.B, ps PeerStore) { - runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { + runBenchmark(b, ps, false, nil, func(i int, ps PeerStore, bd *benchData) error { err := ps.PutSeeder(bd.infohashes[0], bd.peers[i%1000]) if err != nil { return err @@ -108,7 +136,7 @@ func PutDelete1k(b *testing.B, ps PeerStore) { } func PutDelete1kInfohash(b *testing.B, ps PeerStore) { - runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { + runBenchmark(b, ps, false, nil, func(i int, ps PeerStore, bd *benchData) error { err := ps.PutSeeder(bd.infohashes[i%1000], bd.peers[0]) if err != nil { } @@ -117,74 +145,74 @@ func PutDelete1kInfohash(b *testing.B, ps PeerStore) { } func PutDelete1kInfohash1k(b *testing.B, ps PeerStore) { - j := 0 - runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { - err := ps.PutSeeder(bd.infohashes[i%1000], bd.peers[j%1000]) + runBenchmark(b, ps, false, nil, func(i int, ps PeerStore, bd *benchData) error { + err := ps.PutSeeder(bd.infohashes[i%1000], bd.peers[(i*3)%1000]) if err != nil { return err } - err = ps.DeleteSeeder(bd.infohashes[i%1000], bd.peers[j%1000]) - j += 3 + err = ps.DeleteSeeder(bd.infohashes[i%1000], bd.peers[(i*3)%1000]) return err }) } func DeleteNonexist(b *testing.B, ps PeerStore) { - runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { - return ps.DeleteSeeder(bd.infohashes[0], bd.peers[0]) + runBenchmark(b, ps, true, nil, func(i int, ps PeerStore, bd *benchData) error { + ps.DeleteSeeder(bd.infohashes[0], bd.peers[0]) + return nil }) } func DeleteNonexist1k(b *testing.B, ps PeerStore) { - runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { - return ps.DeleteSeeder(bd.infohashes[0], bd.peers[i%1000]) + runBenchmark(b, ps, true, nil, func(i int, ps PeerStore, bd *benchData) error { + ps.DeleteSeeder(bd.infohashes[0], bd.peers[i%1000]) + return nil }) } func DeleteNonexist1kInfohash(b *testing.B, ps PeerStore) { - runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { - return ps.DeleteSeeder(bd.infohashes[i%1000], bd.peers[0]) + runBenchmark(b, ps, true, nil, func(i int, ps PeerStore, bd *benchData) error { + ps.DeleteSeeder(bd.infohashes[i%1000], bd.peers[0]) + return nil }) } func DeleteNonexist1kInfohash1k(b *testing.B, ps PeerStore) { - j := 0 - runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { - err := ps.DeleteSeeder(bd.infohashes[i%1000], bd.peers[j%1000]) - j += 3 - return err + runBenchmark(b, ps, true, nil, func(i int, ps PeerStore, bd *benchData) error { + ps.DeleteSeeder(bd.infohashes[i%1000], bd.peers[(i*3)%1000]) + return nil }) } func GradNonexist(b *testing.B, ps PeerStore) { - runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { - return ps.GraduateLeecher(bd.infohashes[0], bd.peers[0]) + runBenchmark(b, ps, true, nil, func(i int, ps PeerStore, bd *benchData) error { + ps.GraduateLeecher(bd.infohashes[0], bd.peers[0]) + return nil }) } func GradNonexist1k(b *testing.B, ps PeerStore) { - runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { - return ps.GraduateLeecher(bd.infohashes[0], bd.peers[i%1000]) + runBenchmark(b, ps, true, nil, func(i int, ps PeerStore, bd *benchData) error { + ps.GraduateLeecher(bd.infohashes[0], bd.peers[i%1000]) + return nil }) } func GradNonexist1kInfohash(b *testing.B, ps PeerStore) { - runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { - return ps.GraduateLeecher(bd.infohashes[i%1000], bd.peers[0]) + runBenchmark(b, ps, true, nil, func(i int, ps PeerStore, bd *benchData) error { + ps.GraduateLeecher(bd.infohashes[i%1000], bd.peers[0]) + return nil }) } func GradNonexist1kInfohash1k(b *testing.B, ps PeerStore) { - j := 0 - runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { - err := ps.GraduateLeecher(bd.infohashes[i%1000], bd.peers[j%1000]) - j += 3 - return err + runBenchmark(b, ps, true, nil, func(i int, ps PeerStore, bd *benchData) error { + ps.GraduateLeecher(bd.infohashes[i%1000], bd.peers[(i*3)%1000]) + return nil }) } -func GradDelete(b *testing.B, ps PeerStore) { - runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { +func PutGradDelete(b *testing.B, ps PeerStore) { + runBenchmark(b, ps, false, nil, func(i int, ps PeerStore, bd *benchData) error { err := ps.PutLeecher(bd.infohashes[0], bd.peers[0]) if err != nil { return err @@ -197,8 +225,8 @@ func GradDelete(b *testing.B, ps PeerStore) { }) } -func GradDelete1k(b *testing.B, ps PeerStore) { - runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { +func PutGradDelete1k(b *testing.B, ps PeerStore) { + runBenchmark(b, ps, false, nil, func(i int, ps PeerStore, bd *benchData) error { err := ps.PutLeecher(bd.infohashes[0], bd.peers[i%1000]) if err != nil { return err @@ -211,8 +239,8 @@ func GradDelete1k(b *testing.B, ps PeerStore) { }) } -func GradDelete1kInfohash(b *testing.B, ps PeerStore) { - runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { +func PutGradDelete1kInfohash(b *testing.B, ps PeerStore) { + runBenchmark(b, ps, false, nil, func(i int, ps PeerStore, bd *benchData) error { err := ps.PutLeecher(bd.infohashes[i%1000], bd.peers[0]) if err != nil { return err @@ -225,24 +253,22 @@ func GradDelete1kInfohash(b *testing.B, ps PeerStore) { }) } -func GradDelete1kInfohash1k(b *testing.B, ps PeerStore) { - j := 0 - runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { - err := ps.PutLeecher(bd.infohashes[i%1000], bd.peers[j%1000]) +func PutGradDelete1kInfohash1k(b *testing.B, ps PeerStore) { + runBenchmark(b, ps, false, nil, func(i int, ps PeerStore, bd *benchData) error { + err := ps.PutLeecher(bd.infohashes[i%1000], bd.peers[(i*3)%1000]) if err != nil { return err } - err = ps.GraduateLeecher(bd.infohashes[i%1000], bd.peers[j%1000]) + err = ps.GraduateLeecher(bd.infohashes[i%1000], bd.peers[(i*3)%1000]) if err != nil { return err } - err = ps.DeleteSeeder(bd.infohashes[i%1000], bd.peers[j%1000]) - j += 3 + err = ps.DeleteSeeder(bd.infohashes[i%1000], bd.peers[(i*3)%1000]) return err }) } -func generateAnnounceData(ps PeerStore, bd *benchData) error { +func putPeers(ps PeerStore, bd *benchData) error { for i := 0; i < 1000; i++ { for j := 0; j < 1000; j++ { var err error @@ -260,28 +286,28 @@ func generateAnnounceData(ps PeerStore, bd *benchData) error { } func AnnounceLeecher(b *testing.B, ps PeerStore) { - runBenchmark(b, ps, generateAnnounceData, func(i int, ps PeerStore, bd *benchData) error { + runBenchmark(b, ps, true, putPeers, func(i int, ps PeerStore, bd *benchData) error { _, err := ps.AnnouncePeers(bd.infohashes[0], false, 50, bd.peers[0]) return err }) } func AnnounceLeecher1kInfohash(b *testing.B, ps PeerStore) { - runBenchmark(b, ps, generateAnnounceData, func(i int, ps PeerStore, bd *benchData) error { + runBenchmark(b, ps, true, putPeers, func(i int, ps PeerStore, bd *benchData) error { _, err := ps.AnnouncePeers(bd.infohashes[i%1000], false, 50, bd.peers[0]) return err }) } func AnnounceSeeder(b *testing.B, ps PeerStore) { - runBenchmark(b, ps, generateAnnounceData, func(i int, ps PeerStore, bd *benchData) error { + runBenchmark(b, ps, true, putPeers, func(i int, ps PeerStore, bd *benchData) error { _, err := ps.AnnouncePeers(bd.infohashes[0], true, 50, bd.peers[0]) return err }) } func AnnounceSeeder1kInfohash(b *testing.B, ps PeerStore) { - runBenchmark(b, ps, generateAnnounceData, func(i int, ps PeerStore, bd *benchData) error { + runBenchmark(b, ps, true, putPeers, func(i int, ps PeerStore, bd *benchData) error { _, err := ps.AnnouncePeers(bd.infohashes[i%1000], true, 50, bd.peers[0]) return err })