Skip to content

Commit

Permalink
test: add some benchmark testcases
Browse files Browse the repository at this point in the history
  • Loading branch information
ai-chen2050 committed Aug 21, 2024
1 parent 631f30d commit 925d2d7
Show file tree
Hide file tree
Showing 2 changed files with 356 additions and 0 deletions.
180 changes: 180 additions & 0 deletions tests/bench_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package tests

import (
"context"
"fmt"
"sync/atomic"
"testing"
"time"

orbitdb "berty.tech/go-orbit-db"
"berty.tech/go-orbit-db/iface"
"github.com/stretchr/testify/require"
)

// go test -benchmem -run='^$' -bench '^BenchmarkKeyValueStore$' berty.tech/go-orbit-db/tests -v -count=1 -benchtime=1000x
func BenchmarkKeyValueStore(b *testing.B) {
tmpDir, clean := testingTempDirB(b, "db-keystore")
defer clean()

cases := []struct{ Name, Directory string }{
{Name: "in memory", Directory: ":memory:"},
{Name: "persistent", Directory: tmpDir},
}

for _, c := range cases {
b.Run(c.Name, func(b *testing.B) {
testingKeyValueStoreB(b, c.Directory)
})
}
}

// go test -benchmem -run='^$' -bench '^BenchmarkKeyValueStorePB$' berty.tech/go-orbit-db/tests -v -count=1 -benchtime=1000x
func BenchmarkKeyValueStorePB(b *testing.B) {
tmpDir, clean := testingTempDirB(b, "db-keystore")
defer clean()

cases := []struct{ Name, Directory string }{
{Name: "in memory", Directory: ":memory:"},
{Name: "persistent", Directory: tmpDir},
}

// Parallel
for _, c := range cases {
b.Run(c.Name, func(b *testing.B) {
testingKeyValueStorePB(b, c.Directory)
})
}
}

func setupTestingKeyValueStoreB(ctx context.Context, b *testing.B, dir string) (iface.OrbitDB, iface.KeyValueStore, func()) {
b.Helper()

mocknet := testingMockNetB(b)
node, nodeClean := testingIPFSNodeB(ctx, b, mocknet)

db1IPFS := testingCoreAPIB(b, node)

odb, err := orbitdb.NewOrbitDB(ctx, db1IPFS, &orbitdb.NewOrbitDBOptions{
Directory: &dir,
})
require.NoError(b, err)

db, err := odb.KeyValue(ctx, "orbit-db-tests", nil)
require.NoError(b, err)

cleanup := func() {
nodeClean()
odb.Close()
db.Close()
}
return odb, db, cleanup
}

func testingKeyValueStoreB(b *testing.B, dir string) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

b.Run("put", func(b *testing.B) {
_, db, cleanup := setupTestingKeyValueStoreB(ctx, b, dir)
defer cleanup()

b.ResetTimer()
start := time.Now()
for i := 0; i < b.N; i++ {
key := fmt.Sprintf("key%d", i)
value := []byte(fmt.Sprintf("hello%d", i))
_, err := db.Put(ctx, key, value)
require.NoError(b, err)
}
elapsed := time.Since(start)
tps := float64(b.N) / elapsed.Seconds()
b.ReportMetric(tps, "tps")
b.ReportMetric(elapsed.Seconds(), "elapsed_seconds")
})

b.Run("get", func(b *testing.B) {
_, db, cleanup := setupTestingKeyValueStoreB(ctx, b, dir)
defer cleanup()

for i := 0; i < b.N; i++ {
key := fmt.Sprintf("key%d", i)
value := []byte(fmt.Sprintf("hello%d", i))
_, err := db.Put(ctx, key, value)
require.NoError(b, err)
}

b.ResetTimer()
start := time.Now()
for i := 0; i < b.N; i++ {
key := fmt.Sprintf("key%d", i)
value, err := db.Get(ctx, key)
require.NoError(b, err)
require.Equal(b, string(value), fmt.Sprintf("hello%d", i))
}
elapsed := time.Since(start)
tps := float64(b.N) / elapsed.Seconds()
b.ReportMetric(tps, "tps")
b.ReportMetric(elapsed.Seconds(), "elapsed_seconds")
})
}

func testingKeyValueStorePB(b *testing.B, dir string) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

b.Run("pb-put", func(b *testing.B) {
_, db, cleanup := setupTestingKeyValueStoreB(ctx, b, dir)
defer cleanup()

b.ResetTimer()
start := time.Now()
var successCount int64
b.RunParallel(func(pb *testing.PB) {
i := 0
for pb.Next() {
key := fmt.Sprintf("key%d", i)
value := []byte(fmt.Sprintf("hello%d", i))
_, err := db.Put(ctx, key, value)
if err == nil {
atomic.AddInt64(&successCount, 1)
}
i++
}
})
elapsed := time.Since(start)
tps := float64(successCount) / elapsed.Seconds()
b.ReportMetric(tps, "tps")
b.ReportMetric(elapsed.Seconds(), "elapsed_seconds")
})

b.Run("pb-get", func(b *testing.B) {
_, db, cleanup := setupTestingKeyValueStoreB(ctx, b, dir)
defer cleanup()

// Populate the database
for i := 0; i < b.N; i++ {
key := fmt.Sprintf("key%d", i)
value := []byte(fmt.Sprintf("hello%d", i))
_, err := db.Put(ctx, key, value)
require.NoError(b, err)
}

b.ResetTimer()
start := time.Now()
b.RunParallel(func(pb *testing.PB) {
i := 0
for pb.Next() {
key := fmt.Sprintf("key%d", i)
value, err := db.Get(ctx, key)
require.NoError(b, err)
require.Equal(b, string(value), fmt.Sprintf("hello%d", i))
i++
}
})
elapsed := time.Since(start)
tps := float64(b.N) / elapsed.Seconds()
b.ReportMetric(tps, "tps")
b.ReportMetric(elapsed.Seconds(), "elapsed_seconds")
})
}
176 changes: 176 additions & 0 deletions tests/benchmark_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package tests

import (
"context"
"crypto/rand"
"encoding/base64"
"io/ioutil"
"os"
"testing"

"github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"

ds "github.com/ipfs/go-datastore"
dsync "github.com/ipfs/go-datastore/sync"
cfg "github.com/ipfs/kubo/config"
ipfsCore "github.com/ipfs/kubo/core"
"github.com/ipfs/kubo/core/coreapi"
coreiface "github.com/ipfs/kubo/core/coreiface"
mock "github.com/ipfs/kubo/core/mock"
"github.com/ipfs/kubo/repo"
mocknet "github.com/libp2p/go-libp2p/p2p/net/mock"
"github.com/stretchr/testify/require"
)

func testingRepoB(_ context.Context, b *testing.B) repo.Repo {
b.Helper()

c := cfg.Config{}
priv, pub, err := crypto.GenerateKeyPairWithReader(crypto.RSA, 2048, rand.Reader)
require.NoError(b, err)

pid, err := peer.IDFromPublicKey(pub)
require.NoError(b, err)

privkeyb, err := crypto.MarshalPrivateKey(priv)
require.NoError(b, err)

c.Pubsub.Enabled = cfg.True
c.Bootstrap = []string{}
c.Addresses.Swarm = []string{"/ip4/127.0.0.1/tcp/4001", "/ip4/127.0.0.1/udp/4001/quic"}
c.Identity.PeerID = pid.String()
c.Identity.PrivKey = base64.StdEncoding.EncodeToString(privkeyb)
c.Swarm.ResourceMgr.Enabled = cfg.False // we don'b need ressources manager for test

return &repo.Mock{
D: dsync.MutexWrap(ds.NewMapDatastore()),
C: c,
}
}

func testingIPFSAPIsB(ctx context.Context, b *testing.B, count int) ([]coreiface.CoreAPI, func()) {
b.Helper()

mn := testingMockNetB(b)
defer mn.Close()

coreAPIs := make([]coreiface.CoreAPI, count)
cleans := make([]func(), count)

for i := 0; i < count; i++ {
node := (*ipfsCore.IpfsNode)(nil)

node, cleans[i] = testingIPFSNodeB(ctx, b, mn)
coreAPIs[i] = testingCoreAPIB(b, node)
}

return coreAPIs, func() {
for i := 0; i < count; i++ {
cleans[i]()
}
}
}

func testingIPFSAPIsNonMockedB(ctx context.Context, b *testing.B, count int) ([]coreiface.CoreAPI, func()) {
b.Helper()

coreAPIs := make([]coreiface.CoreAPI, count)
cleans := make([]func(), count)

for i := 0; i < count; i++ {
core, err := ipfsCore.NewNode(ctx, &ipfsCore.BuildCfg{
Online: true,
Repo: testingRepoB(ctx, b),
ExtraOpts: map[string]bool{
"pubsub": true,
},
})
require.NoError(b, err)

coreAPIs[i] = testingCoreAPIB(b, core)
cleans[i] = func() {
core.Close()
}
}

return coreAPIs, func() {
for i := 0; i < count; i++ {
cleans[i]()
}
}
}

func testingIPFSNodeWithoutPubsubB(ctx context.Context, b *testing.B, m mocknet.Mocknet) (*ipfsCore.IpfsNode, func()) {
b.Helper()

core, err := ipfsCore.NewNode(ctx, &ipfsCore.BuildCfg{
Online: true,
Repo: testingRepoB(ctx, b),
Host: mock.MockHostOption(m),
ExtraOpts: map[string]bool{
"pubsub": false,
},
})
require.NoError(b, err)

cleanup := func() { core.Close() }
return core, cleanup
}

func testingIPFSNodeB(ctx context.Context, b *testing.B, m mocknet.Mocknet) (*ipfsCore.IpfsNode, func()) {
b.Helper()

core, err := ipfsCore.NewNode(ctx, &ipfsCore.BuildCfg{
Online: true,
Repo: testingRepoB(ctx, b),
Host: mock.MockHostOption(m),
ExtraOpts: map[string]bool{
"pubsub": true,
},
})
require.NoError(b, err)

cleanup := func() { core.Close() }
return core, cleanup
}

func testingNonMockedIPFSNodeB(ctx context.Context, b *testing.B) (*ipfsCore.IpfsNode, func()) {
b.Helper()

core, err := ipfsCore.NewNode(ctx, &ipfsCore.BuildCfg{
Online: true,
Repo: testingRepoB(ctx, b),
ExtraOpts: map[string]bool{
"pubsub": true,
},
})
require.NoError(b, err)

cleanup := func() { core.Close() }
return core, cleanup
}

func testingCoreAPIB(b *testing.B, core *ipfsCore.IpfsNode) coreiface.CoreAPI {
b.Helper()

api, err := coreapi.NewCoreAPI(core)
require.NoError(b, err)
return api
}

func testingMockNetB(b *testing.B) mocknet.Mocknet {
mn := mocknet.New()
b.Cleanup(func() { mn.Close() })
return mn
}

func testingTempDirB(b *testing.B, name string) (string, func()) {
b.Helper()

path, err := ioutil.TempDir("", name)
require.NoError(b, err)

cleanup := func() { os.RemoveAll(path) }
return path, cleanup
}

0 comments on commit 925d2d7

Please sign in to comment.