forked from TrueCloudLab/frostfs-node
[#1262] metabase: Add benchmarks for Put
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
parent
f1223b46df
commit
456e1584d6
4 changed files with 99 additions and 6 deletions
|
@ -22,6 +22,8 @@ func (db *DB) Open() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't open boltDB database: %w", err)
|
return fmt.Errorf("can't open boltDB database: %w", err)
|
||||||
}
|
}
|
||||||
|
db.boltDB.MaxBatchDelay = db.boltBatchDelay
|
||||||
|
db.boltDB.MaxBatchSize = db.boltBatchSize
|
||||||
|
|
||||||
db.log.Debug("opened boltDB instance for Metabase")
|
db.log.Debug("opened boltDB instance for Metabase")
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
v2object "github.com/nspcc-dev/neofs-api-go/v2/object"
|
v2object "github.com/nspcc-dev/neofs-api-go/v2/object"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/util/logger"
|
"github.com/nspcc-dev/neofs-node/pkg/util/logger"
|
||||||
|
@ -30,6 +31,9 @@ type Option func(*cfg)
|
||||||
type cfg struct {
|
type cfg struct {
|
||||||
boltOptions *bbolt.Options // optional
|
boltOptions *bbolt.Options // optional
|
||||||
|
|
||||||
|
boltBatchSize int
|
||||||
|
boltBatchDelay time.Duration
|
||||||
|
|
||||||
info Info
|
info Info
|
||||||
|
|
||||||
log *logger.Logger
|
log *logger.Logger
|
||||||
|
@ -40,8 +44,9 @@ func defaultCfg() *cfg {
|
||||||
info: Info{
|
info: Info{
|
||||||
Permission: os.ModePerm, // 0777
|
Permission: os.ModePerm, // 0777
|
||||||
},
|
},
|
||||||
|
boltBatchDelay: bbolt.DefaultMaxBatchDelay,
|
||||||
log: zap.L(),
|
boltBatchSize: bbolt.DefaultMaxBatchSize,
|
||||||
|
log: zap.L(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,3 +149,21 @@ func WithPermissions(perm fs.FileMode) Option {
|
||||||
c.info.Permission = perm
|
c.info.Permission = perm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithBatchSize returns option to specify maximum concurrent operations
|
||||||
|
// to be processed in a single transactions.
|
||||||
|
// This option is missing from `bbolt.Options` but is set right after DB is open.
|
||||||
|
func WithBatchSize(s int) Option {
|
||||||
|
return func(c *cfg) {
|
||||||
|
c.boltBatchSize = s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithBatchDelay returns option to specify maximum time to wait before
|
||||||
|
// the batch of concurrent transactions is processed.
|
||||||
|
// This option is missing from `bbolt.Options` but is set right after DB is open.
|
||||||
|
func WithBatchDelay(d time.Duration) Option {
|
||||||
|
return func(c *cfg) {
|
||||||
|
c.boltBatchDelay = d
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -46,10 +46,11 @@ func testOID() *oidSDK.ID {
|
||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDB(t testing.TB) *meta.DB {
|
func newDB(t testing.TB, opts ...meta.Option) *meta.DB {
|
||||||
path := t.Name()
|
path := t.Name()
|
||||||
|
|
||||||
bdb := meta.New(meta.WithPath(path), meta.WithPermissions(0600))
|
bdb := meta.New(append([]meta.Option{meta.WithPath(path), meta.WithPermissions(0600)},
|
||||||
|
opts...)...)
|
||||||
|
|
||||||
require.NoError(t, bdb.Open())
|
require.NoError(t, bdb.Open())
|
||||||
|
|
||||||
|
@ -61,11 +62,11 @@ func newDB(t testing.TB) *meta.DB {
|
||||||
return bdb
|
return bdb
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateObject(t *testing.T) *object.Object {
|
func generateObject(t testing.TB) *object.Object {
|
||||||
return generateObjectWithCID(t, cidtest.ID())
|
return generateObjectWithCID(t, cidtest.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateObjectWithCID(t *testing.T, cid *cid.ID) *object.Object {
|
func generateObjectWithCID(t testing.TB, cid *cid.ID) *object.Object {
|
||||||
version := version.New()
|
version := version.New()
|
||||||
version.SetMajor(2)
|
version.SetMajor(2)
|
||||||
version.SetMinor(1)
|
version.SetMinor(1)
|
||||||
|
|
|
@ -1,14 +1,81 @@
|
||||||
package meta_test
|
package meta_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/core/object"
|
"github.com/nspcc-dev/neofs-node/pkg/core/object"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza"
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza"
|
||||||
meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
|
meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
|
||||||
|
"github.com/nspcc-dev/neofs-node/pkg/util/rand"
|
||||||
|
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
|
||||||
|
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
|
||||||
|
objecttest "github.com/nspcc-dev/neofs-sdk-go/object/id/test"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"go.uber.org/atomic"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func prepareObjects(t testing.TB, n int) []*objectSDK.Object {
|
||||||
|
cid := cidtest.ID()
|
||||||
|
parentID := objecttest.ID()
|
||||||
|
objs := make([]*objectSDK.Object, n)
|
||||||
|
for i := range objs {
|
||||||
|
objs[i] = generateObjectWithCID(t, cid)
|
||||||
|
|
||||||
|
// FKBT indices.
|
||||||
|
attrs := make([]objectSDK.Attribute, 20)
|
||||||
|
for j := range attrs {
|
||||||
|
attrs[j].SetKey("abc" + strconv.FormatUint(rand.Uint64()%4, 16))
|
||||||
|
attrs[j].SetValue("xyz" + strconv.FormatUint(rand.Uint64()%4, 16))
|
||||||
|
}
|
||||||
|
objs[i].SetAttributes(attrs...)
|
||||||
|
|
||||||
|
// List indices.
|
||||||
|
if i%2 == 0 {
|
||||||
|
objs[i].SetParentID(parentID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return objs
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkPut(b *testing.B) {
|
||||||
|
b.Run("parallel", func(b *testing.B) {
|
||||||
|
db := newDB(b,
|
||||||
|
meta.WithBatchDelay(time.Millisecond*10),
|
||||||
|
meta.WithBatchSize(runtime.NumCPU()))
|
||||||
|
// Ensure the benchmark is bound by CPU and not waiting batch-delay time.
|
||||||
|
b.SetParallelism(1)
|
||||||
|
|
||||||
|
index := atomic.NewInt64(-1)
|
||||||
|
objs := prepareObjects(b, b.N)
|
||||||
|
b.ResetTimer()
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
|
for pb.Next() {
|
||||||
|
if err := meta.Put(db, objs[index.Inc()], nil); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
b.Run("sequential", func(b *testing.B) {
|
||||||
|
db := newDB(b,
|
||||||
|
meta.WithBatchDelay(time.Millisecond*10),
|
||||||
|
meta.WithBatchSize(1))
|
||||||
|
index := atomic.NewInt64(-1)
|
||||||
|
objs := prepareObjects(b, b.N)
|
||||||
|
b.ResetTimer()
|
||||||
|
b.ReportAllocs()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if err := meta.Put(db, objs[index.Inc()], nil); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestDB_PutBlobovnicaUpdate(t *testing.T) {
|
func TestDB_PutBlobovnicaUpdate(t *testing.T) {
|
||||||
db := newDB(t)
|
db := newDB(t)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue