make benchmarks parallel, fix memory benchmarks

This commit is contained in:
Leo Balduf 2016-08-11 20:02:10 -04:00 committed by Jimmy Zelinskie
parent 651ed50957
commit 6a45107193
2 changed files with 129 additions and 95 deletions

View file

@ -6,27 +6,35 @@ import (
s "github.com/jzelinskie/trakr/storage" s "github.com/jzelinskie/trakr/storage"
) )
func BenchmarkPut(b *testing.B) { s.Put(b, &peerStore{}) } func createNew() s.PeerStore {
func BenchmarkPut1k(b *testing.B) { s.Put1k(b, &peerStore{}) } ps, err := New(Config{ShardCount: 1024})
func BenchmarkPut1kInfohash(b *testing.B) { s.Put1kInfohash(b, &peerStore{}) } if err != nil {
func BenchmarkPut1kInfohash1k(b *testing.B) { s.Put1kInfohash1k(b, &peerStore{}) } panic(err)
func BenchmarkPutDelete(b *testing.B) { s.PutDelete(b, &peerStore{}) } }
func BenchmarkPutDelete1k(b *testing.B) { s.PutDelete1k(b, &peerStore{}) } return ps
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 BenchmarkPut(b *testing.B) { s.Put(b, createNew()) }
func BenchmarkDeleteNonexist1k(b *testing.B) { s.DeleteNonexist1k(b, &peerStore{}) } func BenchmarkPut1k(b *testing.B) { s.Put1k(b, createNew()) }
func BenchmarkDeleteNonexist1kInfohash(b *testing.B) { s.DeleteNonexist1kInfohash(b, &peerStore{}) } func BenchmarkPut1kInfohash(b *testing.B) { s.Put1kInfohash(b, createNew()) }
func BenchmarkDeleteNonexist1kInfohash1k(b *testing.B) { s.DeleteNonexist1kInfohash1k(b, &peerStore{}) } func BenchmarkPut1kInfohash1k(b *testing.B) { s.Put1kInfohash1k(b, createNew()) }
func BenchmarkGradDelete(b *testing.B) { s.GradDelete(b, &peerStore{}) } func BenchmarkPutDelete(b *testing.B) { s.PutDelete(b, createNew()) }
func BenchmarkGradDelete1k(b *testing.B) { s.GradDelete1k(b, &peerStore{}) } func BenchmarkPutDelete1k(b *testing.B) { s.PutDelete1k(b, createNew()) }
func BenchmarkGradDelete1kInfohash(b *testing.B) { s.GradDelete1kInfohash(b, &peerStore{}) } func BenchmarkPutDelete1kInfohash(b *testing.B) { s.PutDelete1kInfohash(b, createNew()) }
func BenchmarkGradDelete1kInfohash1k(b *testing.B) { s.GradDelete1kInfohash1k(b, &peerStore{}) } func BenchmarkPutDelete1kInfohash1k(b *testing.B) { s.PutDelete1kInfohash1k(b, createNew()) }
func BenchmarkGradNonexist(b *testing.B) { s.GradNonexist(b, &peerStore{}) } func BenchmarkDeleteNonexist(b *testing.B) { s.DeleteNonexist(b, createNew()) }
func BenchmarkGradNonexist1k(b *testing.B) { s.GradNonexist1k(b, &peerStore{}) } func BenchmarkDeleteNonexist1k(b *testing.B) { s.DeleteNonexist1k(b, createNew()) }
func BenchmarkGradNonexist1kInfohash(b *testing.B) { s.GradNonexist1kInfohash(b, &peerStore{}) } func BenchmarkDeleteNonexist1kInfohash(b *testing.B) { s.DeleteNonexist1kInfohash(b, createNew()) }
func BenchmarkGradNonexist1kInfohash1k(b *testing.B) { s.GradNonexist1kInfohash1k(b, &peerStore{}) } func BenchmarkDeleteNonexist1kInfohash1k(b *testing.B) { s.DeleteNonexist1kInfohash1k(b, createNew()) }
func BenchmarkAnnounceLeecher(b *testing.B) { s.AnnounceLeecher(b, &peerStore{}) } func BenchmarkPutGradDelete(b *testing.B) { s.PutGradDelete(b, createNew()) }
func BenchmarkAnnounceLeecher1kInfohash(b *testing.B) { s.AnnounceLeecher1kInfohash(b, &peerStore{}) } func BenchmarkPutGradDelete1k(b *testing.B) { s.PutGradDelete1k(b, createNew()) }
func BenchmarkAnnounceSeeder(b *testing.B) { s.AnnounceSeeder(b, &peerStore{}) } func BenchmarkPutGradDelete1kInfohash(b *testing.B) { s.PutGradDelete1kInfohash(b, createNew()) }
func BenchmarkAnnounceSeeder1kInfohash(b *testing.B) { s.AnnounceSeeder1kInfohash(b, &peerStore{}) } 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()) }

View file

@ -1,8 +1,10 @@
package storage package storage
import ( import (
"fmt" "math/rand"
"net" "net"
"runtime"
"sync/atomic"
"testing" "testing"
"github.com/jzelinskie/trakr/bittorrent" "github.com/jzelinskie/trakr/bittorrent"
@ -14,25 +16,37 @@ type benchData struct {
} }
func generateInfohashes() (a [1000]bittorrent.InfoHash) { func generateInfohashes() (a [1000]bittorrent.InfoHash) {
b := make([]byte, 2) r := rand.New(rand.NewSource(0))
for i := range a { for i := range a {
b[0] = byte(i) b := [20]byte{}
b[1] = byte(i >> 8) n, err := r.Read(b[:])
a[i] = bittorrent.InfoHash([20]byte{b[0], b[1]}) if err != nil || n != 20 {
panic("unable to create random bytes")
}
a[i] = bittorrent.InfoHash(b)
} }
return return
} }
func generatePeers() (a [1000]bittorrent.Peer) { func generatePeers() (a [1000]bittorrent.Peer) {
b := make([]byte, 2) r := rand.New(rand.NewSource(0))
for i := range a { for i := range a {
b[0] = byte(i) ip := make([]byte, 4)
b[1] = byte(i >> 8) 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{ a[i] = bittorrent.Peer{
ID: bittorrent.PeerID([20]byte{b[0], b[1]}), ID: bittorrent.PeerID(id),
IP: net.ParseIP(fmt.Sprintf("64.%d.%d.64", b[0], b[1])), IP: net.IP(ip),
Port: uint16(i), Port: port,
} }
} }
@ -42,53 +56,67 @@ func generatePeers() (a [1000]bittorrent.Peer) {
type executionFunc func(int, PeerStore, *benchData) error type executionFunc func(int, PeerStore, *benchData) error
type setupFunc func(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()} bd := &benchData{generateInfohashes(), generatePeers()}
spacing := int32(1000 / runtime.NumCPU())
if sf != nil { if sf != nil {
err := sf(ps, bd) err := sf(ps, bd)
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
} }
offset := int32(0)
b.ResetTimer() b.ResetTimer()
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++ { for i := 0; i < b.N; i++ {
err := ef(i, ps, bd) err := ef(i, ps, bd)
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
} }
}
b.StopTimer() b.StopTimer()
} }
func Put(b *testing.B, ps PeerStore) { 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]) return ps.PutSeeder(bd.infohashes[0], bd.peers[0])
}) })
} }
func Put1k(b *testing.B, ps PeerStore) { 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]) return ps.PutSeeder(bd.infohashes[0], bd.peers[i%1000])
}) })
} }
func Put1kInfohash(b *testing.B, ps PeerStore) { 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]) return ps.PutSeeder(bd.infohashes[i%1000], bd.peers[0])
}) })
} }
func Put1kInfohash1k(b *testing.B, ps PeerStore) { func Put1kInfohash1k(b *testing.B, ps PeerStore) {
j := 0 runBenchmark(b, ps, true, nil, func(i int, ps PeerStore, bd *benchData) error {
runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { err := ps.PutSeeder(bd.infohashes[i%1000], bd.peers[(i*3)%1000])
err := ps.PutSeeder(bd.infohashes[i%1000], bd.peers[j%1000])
j += 3
return err return err
}) })
} }
func PutDelete(b *testing.B, ps PeerStore) { 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]) err := ps.PutSeeder(bd.infohashes[0], bd.peers[0])
if err != nil { if err != nil {
return err return err
@ -98,7 +126,7 @@ func PutDelete(b *testing.B, ps PeerStore) {
} }
func PutDelete1k(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]) err := ps.PutSeeder(bd.infohashes[0], bd.peers[i%1000])
if err != nil { if err != nil {
return err return err
@ -108,7 +136,7 @@ func PutDelete1k(b *testing.B, ps PeerStore) {
} }
func PutDelete1kInfohash(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]) err := ps.PutSeeder(bd.infohashes[i%1000], bd.peers[0])
if err != nil { if err != nil {
} }
@ -117,74 +145,74 @@ func PutDelete1kInfohash(b *testing.B, ps PeerStore) {
} }
func PutDelete1kInfohash1k(b *testing.B, ps PeerStore) { func PutDelete1kInfohash1k(b *testing.B, ps PeerStore) {
j := 0 runBenchmark(b, ps, false, nil, func(i int, ps PeerStore, bd *benchData) error {
runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { err := ps.PutSeeder(bd.infohashes[i%1000], bd.peers[(i*3)%1000])
err := ps.PutSeeder(bd.infohashes[i%1000], bd.peers[j%1000])
if err != nil { if err != nil {
return err return err
} }
err = ps.DeleteSeeder(bd.infohashes[i%1000], bd.peers[j%1000]) err = ps.DeleteSeeder(bd.infohashes[i%1000], bd.peers[(i*3)%1000])
j += 3
return err return err
}) })
} }
func DeleteNonexist(b *testing.B, ps PeerStore) { func DeleteNonexist(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.DeleteSeeder(bd.infohashes[0], bd.peers[0]) ps.DeleteSeeder(bd.infohashes[0], bd.peers[0])
return nil
}) })
} }
func DeleteNonexist1k(b *testing.B, ps PeerStore) { func DeleteNonexist1k(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.DeleteSeeder(bd.infohashes[0], bd.peers[i%1000]) ps.DeleteSeeder(bd.infohashes[0], bd.peers[i%1000])
return nil
}) })
} }
func DeleteNonexist1kInfohash(b *testing.B, ps PeerStore) { func DeleteNonexist1kInfohash(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.DeleteSeeder(bd.infohashes[i%1000], bd.peers[0]) ps.DeleteSeeder(bd.infohashes[i%1000], bd.peers[0])
return nil
}) })
} }
func DeleteNonexist1kInfohash1k(b *testing.B, ps PeerStore) { func DeleteNonexist1kInfohash1k(b *testing.B, ps PeerStore) {
j := 0 runBenchmark(b, ps, true, nil, func(i int, ps PeerStore, bd *benchData) error {
runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { ps.DeleteSeeder(bd.infohashes[i%1000], bd.peers[(i*3)%1000])
err := ps.DeleteSeeder(bd.infohashes[i%1000], bd.peers[j%1000]) return nil
j += 3
return err
}) })
} }
func GradNonexist(b *testing.B, ps PeerStore) { func GradNonexist(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.GraduateLeecher(bd.infohashes[0], bd.peers[0]) ps.GraduateLeecher(bd.infohashes[0], bd.peers[0])
return nil
}) })
} }
func GradNonexist1k(b *testing.B, ps PeerStore) { func GradNonexist1k(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.GraduateLeecher(bd.infohashes[0], bd.peers[i%1000]) ps.GraduateLeecher(bd.infohashes[0], bd.peers[i%1000])
return nil
}) })
} }
func GradNonexist1kInfohash(b *testing.B, ps PeerStore) { func GradNonexist1kInfohash(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.GraduateLeecher(bd.infohashes[i%1000], bd.peers[0]) ps.GraduateLeecher(bd.infohashes[i%1000], bd.peers[0])
return nil
}) })
} }
func GradNonexist1kInfohash1k(b *testing.B, ps PeerStore) { func GradNonexist1kInfohash1k(b *testing.B, ps PeerStore) {
j := 0 runBenchmark(b, ps, true, nil, func(i int, ps PeerStore, bd *benchData) error {
runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { ps.GraduateLeecher(bd.infohashes[i%1000], bd.peers[(i*3)%1000])
err := ps.GraduateLeecher(bd.infohashes[i%1000], bd.peers[j%1000]) return nil
j += 3
return err
}) })
} }
func GradDelete(b *testing.B, ps PeerStore) { func PutGradDelete(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.PutLeecher(bd.infohashes[0], bd.peers[0]) err := ps.PutLeecher(bd.infohashes[0], bd.peers[0])
if err != nil { if err != nil {
return err return err
@ -197,8 +225,8 @@ func GradDelete(b *testing.B, ps PeerStore) {
}) })
} }
func GradDelete1k(b *testing.B, ps PeerStore) { func PutGradDelete1k(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.PutLeecher(bd.infohashes[0], bd.peers[i%1000]) err := ps.PutLeecher(bd.infohashes[0], bd.peers[i%1000])
if err != nil { if err != nil {
return err return err
@ -211,8 +239,8 @@ func GradDelete1k(b *testing.B, ps PeerStore) {
}) })
} }
func GradDelete1kInfohash(b *testing.B, ps PeerStore) { func PutGradDelete1kInfohash(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.PutLeecher(bd.infohashes[i%1000], bd.peers[0]) err := ps.PutLeecher(bd.infohashes[i%1000], bd.peers[0])
if err != nil { if err != nil {
return err return err
@ -225,24 +253,22 @@ func GradDelete1kInfohash(b *testing.B, ps PeerStore) {
}) })
} }
func GradDelete1kInfohash1k(b *testing.B, ps PeerStore) { func PutGradDelete1kInfohash1k(b *testing.B, ps PeerStore) {
j := 0 runBenchmark(b, ps, false, nil, func(i int, ps PeerStore, bd *benchData) error {
runBenchmark(b, ps, nil, func(i int, ps PeerStore, bd *benchData) error { err := ps.PutLeecher(bd.infohashes[i%1000], bd.peers[(i*3)%1000])
err := ps.PutLeecher(bd.infohashes[i%1000], bd.peers[j%1000])
if err != nil { if err != nil {
return err 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 { if err != nil {
return err return err
} }
err = ps.DeleteSeeder(bd.infohashes[i%1000], bd.peers[j%1000]) err = ps.DeleteSeeder(bd.infohashes[i%1000], bd.peers[(i*3)%1000])
j += 3
return err return err
}) })
} }
func generateAnnounceData(ps PeerStore, bd *benchData) error { func putPeers(ps PeerStore, bd *benchData) error {
for i := 0; i < 1000; i++ { for i := 0; i < 1000; i++ {
for j := 0; j < 1000; j++ { for j := 0; j < 1000; j++ {
var err error var err error
@ -260,28 +286,28 @@ func generateAnnounceData(ps PeerStore, bd *benchData) error {
} }
func AnnounceLeecher(b *testing.B, ps PeerStore) { 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]) _, err := ps.AnnouncePeers(bd.infohashes[0], false, 50, bd.peers[0])
return err return err
}) })
} }
func AnnounceLeecher1kInfohash(b *testing.B, ps PeerStore) { 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]) _, err := ps.AnnouncePeers(bd.infohashes[i%1000], false, 50, bd.peers[0])
return err return err
}) })
} }
func AnnounceSeeder(b *testing.B, ps PeerStore) { 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]) _, err := ps.AnnouncePeers(bd.infohashes[0], true, 50, bd.peers[0])
return err return err
}) })
} }
func AnnounceSeeder1kInfohash(b *testing.B, ps PeerStore) { 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]) _, err := ps.AnnouncePeers(bd.infohashes[i%1000], true, 50, bd.peers[0])
return err return err
}) })