From 31581bc1c3971a43a3efa231c1cb15e4701a47ec Mon Sep 17 00:00:00 2001 From: Leo Balduf Date: Sun, 19 Jun 2016 12:55:45 -0400 Subject: [PATCH] store: add PeerStore benchmarks --- server/store/memory/peer_store_test.go | 117 +++++- server/store/store_bench.go | 481 +++++++++++++++++++++++++ 2 files changed, 596 insertions(+), 2 deletions(-) diff --git a/server/store/memory/peer_store_test.go b/server/store/memory/peer_store_test.go index 0da3ff6..9a00b17 100644 --- a/server/store/memory/peer_store_test.go +++ b/server/store/memory/peer_store_test.go @@ -11,8 +11,9 @@ import ( ) var ( - peerStoreTester = store.PreparePeerStoreTester(&peerStoreDriver{}) - peerStoreTestConfig = &store.DriverConfig{} + peerStoreTester = store.PreparePeerStoreTester(&peerStoreDriver{}) + peerStoreBenchmarker = store.PreparePeerStoreBenchmarker(&peerStoreDriver{}) + peerStoreTestConfig = &store.DriverConfig{} ) func init() { @@ -27,3 +28,115 @@ func init() { func TestPeerStore(t *testing.T) { peerStoreTester.TestPeerStore(t, peerStoreTestConfig) } + +func BenchmarkPeerStore_PutSeeder(b *testing.B) { + peerStoreBenchmarker.PutSeeder(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_PutSeeder1KInfohash(b *testing.B) { + peerStoreBenchmarker.PutSeeder1KInfohash(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_PutSeeder1KSeeders(b *testing.B) { + peerStoreBenchmarker.PutSeeder1KSeeders(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_PutSeeder1KInfohash1KSeeders(b *testing.B) { + peerStoreBenchmarker.PutSeeder1KInfohash1KSeeders(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_PutDeleteSeeder(b *testing.B) { + peerStoreBenchmarker.PutDeleteSeeder(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_PutDeleteSeeder1KInfohash(b *testing.B) { + peerStoreBenchmarker.PutDeleteSeeder1KInfohash(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_PutDeleteSeeder1KSeeders(b *testing.B) { + peerStoreBenchmarker.PutDeleteSeeder1KSeeders(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_PutDeleteSeeder1KInfohash1KSeeders(b *testing.B) { + peerStoreBenchmarker.PutDeleteSeeder1KInfohash1KSeeders(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_DeleteSeederNonExist(b *testing.B) { + peerStoreBenchmarker.DeleteSeederNonExist(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_DeleteSeederNonExist1KInfohash(b *testing.B) { + peerStoreBenchmarker.DeleteSeederNonExist1KInfohash(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_DeleteSeederNonExist1KSeeders(b *testing.B) { + peerStoreBenchmarker.DeleteSeederNonExist1KSeeders(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_DeleteSeederNonExist1KInfohash1KSeeders(b *testing.B) { + peerStoreBenchmarker.DeleteSeederNonExist1KInfohash1KSeeders(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_PutGraduateDeleteLeecher(b *testing.B) { + peerStoreBenchmarker.PutGraduateDeleteLeecher(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_PutGraduateDeleteLeecher1KInfohash(b *testing.B) { + peerStoreBenchmarker.PutGraduateDeleteLeecher1KInfohash(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_PutGraduateDeleteLeecher1KSeeders(b *testing.B) { + peerStoreBenchmarker.PutGraduateDeleteLeecher1KLeechers(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_PutGraduateDeleteLeecher1KInfohash1KSeeders(b *testing.B) { + peerStoreBenchmarker.PutGraduateDeleteLeecher1KInfohash1KLeechers(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_GraduateLeecherNonExist(b *testing.B) { + peerStoreBenchmarker.GraduateLeecherNonExist(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_GraduateLeecherNonExist1KInfohash(b *testing.B) { + peerStoreBenchmarker.GraduateLeecherNonExist1KInfohash(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_GraduateLeecherNonExist1KSeeders(b *testing.B) { + peerStoreBenchmarker.GraduateLeecherNonExist1KLeechers(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_GraduateLeecherNonExist1KInfohash1KSeeders(b *testing.B) { + peerStoreBenchmarker.GraduateLeecherNonExist1KInfohash1KLeechers(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_AnnouncePeers(b *testing.B) { + peerStoreBenchmarker.AnnouncePeers(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_AnnouncePeers1KInfohash(b *testing.B) { + peerStoreBenchmarker.AnnouncePeers1KInfohash(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_AnnouncePeersSeeder(b *testing.B) { + peerStoreBenchmarker.AnnouncePeersSeeder(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_AnnouncePeersSeeder1KInfohash(b *testing.B) { + peerStoreBenchmarker.AnnouncePeersSeeder1KInfohash(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_GetSeeders(b *testing.B) { + peerStoreBenchmarker.GetSeeders(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_GetSeeders1KInfohash(b *testing.B) { + peerStoreBenchmarker.GetSeeders1KInfohash(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_NumSeeders(b *testing.B) { + peerStoreBenchmarker.NumSeeders(b, peerStoreTestConfig) +} + +func BenchmarkPeerStore_NumSeeders1KInfohash(b *testing.B) { + peerStoreBenchmarker.NumSeeders1KInfohash(b, peerStoreTestConfig) +} diff --git a/server/store/store_bench.go b/server/store/store_bench.go index c1b56f3..9e313a3 100644 --- a/server/store/store_bench.go +++ b/server/store/store_bench.go @@ -10,6 +10,7 @@ import ( "strings" "testing" + "github.com/chihaya/chihaya" "github.com/stretchr/testify/require" ) @@ -777,3 +778,483 @@ func (ib ipStoreBench) RemoveNonExist1KV6Network(b *testing.B, cfg *DriverConfig return nil }) } + +// PeerStoreBenchmarker is a collection of benchmarks for PeerStore drivers. +// Every benchmark expects a new, clean storage. Every benchmark should be +// called with a DriverConfig that ensures this. +type PeerStoreBenchmarker interface { + PutSeeder(*testing.B, *DriverConfig) + PutSeeder1KInfohash(*testing.B, *DriverConfig) + PutSeeder1KSeeders(*testing.B, *DriverConfig) + PutSeeder1KInfohash1KSeeders(*testing.B, *DriverConfig) + + PutDeleteSeeder(*testing.B, *DriverConfig) + PutDeleteSeeder1KInfohash(*testing.B, *DriverConfig) + PutDeleteSeeder1KSeeders(*testing.B, *DriverConfig) + PutDeleteSeeder1KInfohash1KSeeders(*testing.B, *DriverConfig) + + DeleteSeederNonExist(*testing.B, *DriverConfig) + DeleteSeederNonExist1KInfohash(*testing.B, *DriverConfig) + DeleteSeederNonExist1KSeeders(*testing.B, *DriverConfig) + DeleteSeederNonExist1KInfohash1KSeeders(*testing.B, *DriverConfig) + + PutGraduateDeleteLeecher(*testing.B, *DriverConfig) + PutGraduateDeleteLeecher1KInfohash(*testing.B, *DriverConfig) + PutGraduateDeleteLeecher1KLeechers(*testing.B, *DriverConfig) + PutGraduateDeleteLeecher1KInfohash1KLeechers(*testing.B, *DriverConfig) + + GraduateLeecherNonExist(*testing.B, *DriverConfig) + GraduateLeecherNonExist1KInfohash(*testing.B, *DriverConfig) + GraduateLeecherNonExist1KLeechers(*testing.B, *DriverConfig) + GraduateLeecherNonExist1KInfohash1KLeechers(*testing.B, *DriverConfig) + + AnnouncePeers(*testing.B, *DriverConfig) + AnnouncePeers1KInfohash(*testing.B, *DriverConfig) + AnnouncePeersSeeder(*testing.B, *DriverConfig) + AnnouncePeersSeeder1KInfohash(*testing.B, *DriverConfig) + + GetSeeders(*testing.B, *DriverConfig) + GetSeeders1KInfohash(*testing.B, *DriverConfig) + + NumSeeders(*testing.B, *DriverConfig) + NumSeeders1KInfohash(*testing.B, *DriverConfig) +} + +type peerStoreBench struct { + infohashes [num1KElements]chihaya.InfoHash + peers [num1KElements]chihaya.Peer + driver PeerStoreDriver +} + +func generateInfohashes() (a [num1KElements]chihaya.InfoHash) { + b := make([]byte, 2) + for i := range a { + b[0] = byte(i) + b[1] = byte(i >> 8) + a[i] = chihaya.InfoHash([20]byte{b[0], b[1]}) + } + + return +} + +func generatePeers() (a [num1KElements]chihaya.Peer) { + b := make([]byte, 2) + for i := range a { + b[0] = byte(i) + b[1] = byte(i >> 8) + a[i] = chihaya.Peer{ + ID: chihaya.PeerID([20]byte{b[0], b[1]}), + IP: net.ParseIP(fmt.Sprintf("64.%d.%d.64", b[0], b[1])), + Port: uint16(i), + } + } + + return +} + +// PreparePeerStoreBenchmarker prepares a reusable suite for PeerStore driver +// benchmarks. +func PreparePeerStoreBenchmarker(driver PeerStoreDriver) PeerStoreBenchmarker { + return peerStoreBench{ + driver: driver, + } +} + +type peerStoreSetupFunc func(PeerStore) error + +func peerStoreSetupNOP(PeerStore) error { return nil } + +type peerStoreBenchFunc func(PeerStore, int) error + +func (pb peerStoreBench) runBenchmark(b *testing.B, cfg *DriverConfig, setup peerStoreSetupFunc, execute peerStoreBenchFunc) { + ps, err := pb.driver.New(cfg) + require.Nil(b, err, "Constructor error must be nil") + require.NotNil(b, ps, "Peer store must not be nil") + + err = setup(ps) + require.Nil(b, err, "Benchmark setup must not fail") + + b.ResetTimer() + for i := 0; i < b.N; i++ { + execute(ps, i) + } + b.StopTimer() + + errChan := ps.Stop() + err = <-errChan + require.Nil(b, err, "PeerStore shutdown must not fail") +} + +func (pb peerStoreBench) PutSeeder(b *testing.B, cfg *DriverConfig) { + pb.runBenchmark(b, cfg, peerStoreSetupNOP, + func(ps PeerStore, i int) error { + ps.PutSeeder(pb.infohashes[0], pb.peers[0]) + return nil + }) +} + +func (pb peerStoreBench) PutSeeder1KInfohash(b *testing.B, cfg *DriverConfig) { + pb.runBenchmark(b, cfg, peerStoreSetupNOP, + func(ps PeerStore, i int) error { + ps.PutSeeder(pb.infohashes[i%num1KElements], pb.peers[0]) + return nil + }) +} + +func (pb peerStoreBench) PutSeeder1KSeeders(b *testing.B, cfg *DriverConfig) { + pb.runBenchmark(b, cfg, peerStoreSetupNOP, + func(ps PeerStore, i int) error { + ps.PutSeeder(pb.infohashes[0], pb.peers[i%num1KElements]) + return nil + }) +} + +func (pb peerStoreBench) PutSeeder1KInfohash1KSeeders(b *testing.B, cfg *DriverConfig) { + j := 0 + pb.runBenchmark(b, cfg, peerStoreSetupNOP, + func(ps PeerStore, i int) error { + ps.PutSeeder(pb.infohashes[i%num1KElements], pb.peers[j%num1KElements]) + j += 3 + return nil + }) +} + +func (pb peerStoreBench) PutDeleteSeeder(b *testing.B, cfg *DriverConfig) { + pb.runBenchmark(b, cfg, peerStoreSetupNOP, + func(ps PeerStore, i int) error { + ps.PutSeeder(pb.infohashes[0], pb.peers[0]) + ps.DeleteSeeder(pb.infohashes[0], pb.peers[0]) + return nil + }) +} + +func (pb peerStoreBench) PutDeleteSeeder1KInfohash(b *testing.B, cfg *DriverConfig) { + pb.runBenchmark(b, cfg, peerStoreSetupNOP, + func(ps PeerStore, i int) error { + ps.PutSeeder(pb.infohashes[i%num1KElements], pb.peers[0]) + ps.DeleteSeeder(pb.infohashes[i%num1KElements], pb.peers[0]) + return nil + }) +} + +func (pb peerStoreBench) PutDeleteSeeder1KSeeders(b *testing.B, cfg *DriverConfig) { + pb.runBenchmark(b, cfg, peerStoreSetupNOP, + func(ps PeerStore, i int) error { + ps.PutSeeder(pb.infohashes[0], pb.peers[i%num1KElements]) + ps.DeleteSeeder(pb.infohashes[0], pb.peers[i%num1KElements]) + return nil + }) +} + +func (pb peerStoreBench) PutDeleteSeeder1KInfohash1KSeeders(b *testing.B, cfg *DriverConfig) { + j := 0 + pb.runBenchmark(b, cfg, peerStoreSetupNOP, + func(ps PeerStore, i int) error { + ps.PutSeeder(pb.infohashes[i%num1KElements], pb.peers[j%num1KElements]) + ps.DeleteSeeder(pb.infohashes[i%num1KElements], pb.peers[j%num1KElements]) + j += 3 + return nil + }) +} + +func (pb peerStoreBench) DeleteSeederNonExist(b *testing.B, cfg *DriverConfig) { + pb.runBenchmark(b, cfg, peerStoreSetupNOP, + func(ps PeerStore, i int) error { + ps.DeleteSeeder(pb.infohashes[0], pb.peers[0]) + return nil + }) +} + +func (pb peerStoreBench) DeleteSeederNonExist1KInfohash(b *testing.B, cfg *DriverConfig) { + pb.runBenchmark(b, cfg, peerStoreSetupNOP, + func(ps PeerStore, i int) error { + ps.DeleteSeeder(pb.infohashes[i%num1KElements], pb.peers[0]) + return nil + }) +} + +func (pb peerStoreBench) DeleteSeederNonExist1KSeeders(b *testing.B, cfg *DriverConfig) { + pb.runBenchmark(b, cfg, peerStoreSetupNOP, + func(ps PeerStore, i int) error { + ps.DeleteSeeder(pb.infohashes[0], pb.peers[i%num1KElements]) + return nil + }) +} + +func (pb peerStoreBench) DeleteSeederNonExist1KInfohash1KSeeders(b *testing.B, cfg *DriverConfig) { + j := 0 + pb.runBenchmark(b, cfg, peerStoreSetupNOP, + func(ps PeerStore, i int) error { + ps.DeleteSeeder(pb.infohashes[i%num1KElements], pb.peers[j%num1KElements]) + j += 3 + return nil + }) +} + +func (pb peerStoreBench) GraduateLeecherNonExist(b *testing.B, cfg *DriverConfig) { + pb.runBenchmark(b, cfg, peerStoreSetupNOP, + func(ps PeerStore, i int) error { + ps.GraduateLeecher(pb.infohashes[0], pb.peers[0]) + return nil + }) +} + +func (pb peerStoreBench) GraduateLeecherNonExist1KInfohash(b *testing.B, cfg *DriverConfig) { + pb.runBenchmark(b, cfg, peerStoreSetupNOP, + func(ps PeerStore, i int) error { + ps.GraduateLeecher(pb.infohashes[i%num1KElements], pb.peers[0]) + return nil + }) +} + +func (pb peerStoreBench) GraduateLeecherNonExist1KLeechers(b *testing.B, cfg *DriverConfig) { + pb.runBenchmark(b, cfg, peerStoreSetupNOP, + func(ps PeerStore, i int) error { + ps.GraduateLeecher(pb.infohashes[0], pb.peers[i%num1KElements]) + return nil + }) +} + +func (pb peerStoreBench) GraduateLeecherNonExist1KInfohash1KLeechers(b *testing.B, cfg *DriverConfig) { + j := 0 + pb.runBenchmark(b, cfg, peerStoreSetupNOP, + func(ps PeerStore, i int) error { + ps.GraduateLeecher(pb.infohashes[i%num1KElements], pb.peers[j%num1KElements]) + j += 3 + return nil + }) +} + +func (pb peerStoreBench) PutGraduateDeleteLeecher(b *testing.B, cfg *DriverConfig) { + pb.runBenchmark(b, cfg, peerStoreSetupNOP, + func(ps PeerStore, i int) error { + ps.PutLeecher(pb.infohashes[0], pb.peers[0]) + ps.GraduateLeecher(pb.infohashes[0], pb.peers[0]) + ps.DeleteSeeder(pb.infohashes[0], pb.peers[0]) + return nil + }) +} + +func (pb peerStoreBench) PutGraduateDeleteLeecher1KInfohash(b *testing.B, cfg *DriverConfig) { + pb.runBenchmark(b, cfg, peerStoreSetupNOP, + func(ps PeerStore, i int) error { + ps.PutLeecher(pb.infohashes[i%num1KElements], pb.peers[0]) + ps.GraduateLeecher(pb.infohashes[i%num1KElements], pb.peers[0]) + ps.DeleteSeeder(pb.infohashes[i%num1KElements], pb.peers[0]) + return nil + }) +} + +func (pb peerStoreBench) PutGraduateDeleteLeecher1KLeechers(b *testing.B, cfg *DriverConfig) { + pb.runBenchmark(b, cfg, peerStoreSetupNOP, + func(ps PeerStore, i int) error { + ps.PutLeecher(pb.infohashes[0], pb.peers[i%num1KElements]) + ps.GraduateLeecher(pb.infohashes[0], pb.peers[i%num1KElements]) + ps.DeleteSeeder(pb.infohashes[0], pb.peers[i%num1KElements]) + return nil + }) +} + +func (pb peerStoreBench) PutGraduateDeleteLeecher1KInfohash1KLeechers(b *testing.B, cfg *DriverConfig) { + j := 0 + pb.runBenchmark(b, cfg, peerStoreSetupNOP, + func(ps PeerStore, i int) error { + ps.PutLeecher(pb.infohashes[i%num1KElements], pb.peers[j%num1KElements]) + ps.GraduateLeecher(pb.infohashes[i%num1KElements], pb.peers[j%num1KElements]) + ps.DeleteSeeder(pb.infohashes[i%num1KElements], pb.peers[j%num1KElements]) + j += 3 + return nil + }) +} + +func (pb peerStoreBench) AnnouncePeers(b *testing.B, cfg *DriverConfig) { + pb.runBenchmark(b, cfg, + func(ps PeerStore) error { + for i := 0; i < num1KElements; i++ { + for j := 0; j < num1KElements; j++ { + var err error + if j < num1KElements/2 { + err = ps.PutLeecher(pb.infohashes[i], pb.peers[j]) + } else { + err = ps.PutSeeder(pb.infohashes[i], pb.peers[j]) + } + if err != nil { + return err + } + } + } + return nil + }, + func(ps PeerStore, i int) error { + ps.AnnouncePeers(pb.infohashes[0], false, 50, pb.peers[0], chihaya.Peer{}) + return nil + }) +} + +func (pb peerStoreBench) AnnouncePeers1KInfohash(b *testing.B, cfg *DriverConfig) { + pb.runBenchmark(b, cfg, + func(ps PeerStore) error { + for i := 0; i < num1KElements; i++ { + for j := 0; j < num1KElements; j++ { + var err error + if j < num1KElements/2 { + err = ps.PutLeecher(pb.infohashes[i], pb.peers[j]) + } else { + err = ps.PutSeeder(pb.infohashes[i], pb.peers[j]) + } + if err != nil { + return err + } + } + } + return nil + }, + func(ps PeerStore, i int) error { + ps.AnnouncePeers(pb.infohashes[i%num1KElements], false, 50, pb.peers[0], chihaya.Peer{}) + return nil + }) +} + +func (pb peerStoreBench) AnnouncePeersSeeder(b *testing.B, cfg *DriverConfig) { + pb.runBenchmark(b, cfg, + func(ps PeerStore) error { + for i := 0; i < num1KElements; i++ { + for j := 0; j < num1KElements; j++ { + var err error + if j < num1KElements/2 { + err = ps.PutLeecher(pb.infohashes[i], pb.peers[j]) + } else { + err = ps.PutSeeder(pb.infohashes[i], pb.peers[j]) + } + if err != nil { + return err + } + } + } + return nil + }, + func(ps PeerStore, i int) error { + ps.AnnouncePeers(pb.infohashes[0], true, 50, pb.peers[0], chihaya.Peer{}) + return nil + }) +} + +func (pb peerStoreBench) AnnouncePeersSeeder1KInfohash(b *testing.B, cfg *DriverConfig) { + pb.runBenchmark(b, cfg, + func(ps PeerStore) error { + for i := 0; i < num1KElements; i++ { + for j := 0; j < num1KElements; j++ { + var err error + if j < num1KElements/2 { + err = ps.PutLeecher(pb.infohashes[i], pb.peers[j]) + } else { + err = ps.PutSeeder(pb.infohashes[i], pb.peers[j]) + } + if err != nil { + return err + } + } + } + return nil + }, + func(ps PeerStore, i int) error { + ps.AnnouncePeers(pb.infohashes[i%num1KElements], true, 50, pb.peers[0], chihaya.Peer{}) + return nil + }) +} + +func (pb peerStoreBench) GetSeeders(b *testing.B, cfg *DriverConfig) { + pb.runBenchmark(b, cfg, + func(ps PeerStore) error { + for i := 0; i < num1KElements; i++ { + for j := 0; j < num1KElements; j++ { + var err error + if j < num1KElements/2 { + err = ps.PutLeecher(pb.infohashes[i], pb.peers[j]) + } else { + err = ps.PutSeeder(pb.infohashes[i], pb.peers[j]) + } + if err != nil { + return err + } + } + } + return nil + }, + func(ps PeerStore, i int) error { + ps.GetSeeders(pb.infohashes[0]) + return nil + }) +} + +func (pb peerStoreBench) GetSeeders1KInfohash(b *testing.B, cfg *DriverConfig) { + pb.runBenchmark(b, cfg, + func(ps PeerStore) error { + for i := 0; i < num1KElements; i++ { + for j := 0; j < num1KElements; j++ { + var err error + if j < num1KElements/2 { + err = ps.PutLeecher(pb.infohashes[i], pb.peers[j]) + } else { + err = ps.PutSeeder(pb.infohashes[i], pb.peers[j]) + } + if err != nil { + return err + } + } + } + return nil + }, + func(ps PeerStore, i int) error { + ps.GetSeeders(pb.infohashes[i%num1KElements]) + return nil + }) +} + +func (pb peerStoreBench) NumSeeders(b *testing.B, cfg *DriverConfig) { + pb.runBenchmark(b, cfg, + func(ps PeerStore) error { + for i := 0; i < num1KElements; i++ { + for j := 0; j < num1KElements; j++ { + var err error + if j < num1KElements/2 { + err = ps.PutLeecher(pb.infohashes[i], pb.peers[j]) + } else { + err = ps.PutSeeder(pb.infohashes[i], pb.peers[j]) + } + if err != nil { + return err + } + } + } + return nil + }, + func(ps PeerStore, i int) error { + ps.NumSeeders(pb.infohashes[0]) + return nil + }) +} + +func (pb peerStoreBench) NumSeeders1KInfohash(b *testing.B, cfg *DriverConfig) { + pb.runBenchmark(b, cfg, + func(ps PeerStore) error { + for i := 0; i < num1KElements; i++ { + for j := 0; j < num1KElements; j++ { + var err error + if j < num1KElements/2 { + err = ps.PutLeecher(pb.infohashes[i], pb.peers[j]) + } else { + err = ps.PutSeeder(pb.infohashes[i], pb.peers[j]) + } + if err != nil { + return err + } + } + } + return nil + }, + func(ps PeerStore, i int) error { + ps.NumSeeders(pb.infohashes[i%num1KElements]) + return nil + }) +}