Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 133 additions & 0 deletions pkg/local_object_storage/blobstor/fstree/bench_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package fstree_test

import (
"io"
"testing"

"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/fstree"
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
"github.com/stretchr/testify/require"
)

func BenchmarkFSTree_Head(b *testing.B) {
for _, size := range payloadSizes {
b.Run(generateSizeLabel(size), func(b *testing.B) {
runReadBenchmark(b, "Head", size)
})
}
}

func BenchmarkFSTree_Get(b *testing.B) {
for _, size := range payloadSizes {
b.Run(generateSizeLabel(size), func(b *testing.B) {
runReadBenchmark(b, "Get", size)
})
}
}

func BenchmarkFSTree_GetStream(b *testing.B) {
for _, size := range payloadSizes {
b.Run(generateSizeLabel(size), func(b *testing.B) {
runReadBenchmark(b, "GetStream", size)

b.Run("GetStream_with_payload_read", func(b *testing.B) {
freshFSTree := setupFSTree(b)
addr := prepareSingleObject(b, freshFSTree, size)

b.ReportAllocs()
b.ResetTimer()
for range b.N {
header, reader, err := freshFSTree.GetStream(addr)
if err != nil {
b.Fatal(err)
}
if header == nil {
b.Fatal("header is nil")
}
if reader != nil {
// Read all payload to simulate real usage
_, err := io.ReadAll(reader)
if err != nil {
b.Fatal(err)
}
require.NoError(b, reader.Close())
}
}
})
})
}
}

func runReadBenchmark(b *testing.B, methodName string, payloadSize int) {
testRead := func(fsTree *fstree.FSTree, addr oid.Address) {
var err error
switch methodName {
case "Head":
_, err = fsTree.Head(addr)
case "Get":
_, err = fsTree.Get(addr)
case "GetStream":
var (
header *objectSDK.Object
reader io.ReadCloser
)
header, reader, err = fsTree.GetStream(addr)
if header == nil {
b.Fatal("header is nil")
}
if reader != nil {
require.NoError(b, reader.Close())
}
}
if err != nil {
b.Fatal(err)
}
}

b.Run(methodName+"_regular", func(b *testing.B) {
fsTree := setupFSTree(b)
addr := prepareSingleObject(b, fsTree, payloadSize)

b.ReportAllocs()
b.ResetTimer()
for range b.N {
testRead(fsTree, addr)
}
})

b.Run(methodName+"_combined", func(b *testing.B) {
fsTree := setupFSTree(b)
addrs := prepareMultipleObjects(b, fsTree, payloadSize)

b.ReportAllocs()
b.ResetTimer()
for k := range b.N {
testRead(fsTree, addrs[k%len(addrs)])
}
})

b.Run(methodName+"_compressed", func(b *testing.B) {
fsTree := setupFSTree(b)
setupCompressor(b, fsTree)
addr := prepareSingleObject(b, fsTree, payloadSize)

b.ReportAllocs()
b.ResetTimer()
for range b.N {
testRead(fsTree, addr)
}
})

b.Run(methodName+"_compressed_combined", func(b *testing.B) {
fsTree := setupFSTree(b)
setupCompressor(b, fsTree)
addrs := prepareMultipleObjects(b, fsTree, payloadSize)

b.ReportAllocs()
b.ResetTimer()
for k := range b.N {
testRead(fsTree, addrs[k%len(addrs)])
}
})
}
100 changes: 100 additions & 0 deletions pkg/local_object_storage/blobstor/fstree/common_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package fstree_test

import (
"crypto/rand"
"fmt"
"testing"

"github.com/nspcc-dev/neofs-node/pkg/core/object"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/compression"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/fstree"
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
objecttest "github.com/nspcc-dev/neofs-sdk-go/object/test"
"github.com/stretchr/testify/require"
)

var payloadSizes = []int{
0, // Empty payload
100, // 100 bytes
4 * 1024, // 4 KB
16 * 1024, // 16 KB
32 * 1024, // 32 KB
100 * 1024, // 100 KB
1024 * 1024, // 1 MB
}

func setupFSTree(tb testing.TB) *fstree.FSTree {
fsTree := fstree.New(fstree.WithPath(tb.TempDir()))
require.NoError(tb, fsTree.Open(false))
require.NoError(tb, fsTree.Init())
return fsTree
}

func setupCompressor(tb testing.TB, fsTree *fstree.FSTree) {
compressConfig := &compression.Config{
Enabled: true,
}
require.NoError(tb, compressConfig.Init())
fsTree.SetCompressor(compressConfig)
}

func prepareSingleObject(tb testing.TB, fsTree *fstree.FSTree, payloadSize int) oid.Address {
obj := generateTestObject(payloadSize)
addr := object.AddressOf(obj)
require.NoError(tb, fsTree.Put(addr, obj.Marshal()))
return addr
}

func addAttribute(obj *objectSDK.Object, key, value string) {
var attr objectSDK.Attribute
attr.SetKey(key)
attr.SetValue(value)

attrs := obj.Attributes()
attrs = append(attrs, attr)
obj.SetAttributes(attrs...)
}

func generateTestObject(payloadSize int) *objectSDK.Object {
obj := objecttest.Object()
if payloadSize > 0 {
payload := make([]byte, payloadSize)
_, _ = rand.Read(payload)
obj.SetPayload(payload)
} else {
obj.SetPayload(nil)
}
obj.SetPayloadSize(uint64(payloadSize))

return &obj
}

func generateSizeLabel(size int) string {
switch {
case size == 0:
return "Empty"
case size < 1024:
return fmt.Sprintf("%dB", size)
case size < 1024*1024:
return fmt.Sprintf("%dKB", size/1024)
default:
return fmt.Sprintf("%dMB", size/(1024*1024))
}
}

func prepareMultipleObjects(tb testing.TB, fsTree *fstree.FSTree, payloadSize int) []oid.Address {
const numObjects = 10
objMap := make(map[oid.Address][]byte, numObjects)
addrs := make([]oid.Address, numObjects)

for i := range numObjects {
obj := generateTestObject(payloadSize)
addr := object.AddressOf(obj)
objMap[addr] = obj.Marshal()
addrs[i] = addr
}

require.NoError(tb, fsTree.PutBatch(objMap))
return addrs
}
62 changes: 3 additions & 59 deletions pkg/local_object_storage/blobstor/fstree/head_bench_test.go
Original file line number Diff line number Diff line change
@@ -1,28 +1,9 @@
package fstree_test

import (
"crypto/rand"
"fmt"
"testing"

"github.com/nspcc-dev/neofs-node/pkg/core/object"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/compression"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/fstree"
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
objecttest "github.com/nspcc-dev/neofs-sdk-go/object/test"
"github.com/stretchr/testify/require"
)

var payloadSizes = []int{
0, // Empty payload
100, // 100 bytes
4 * 1024, // 4 KB
16 * 1024, // 16 KB
32 * 1024, // 32 KB
100 * 1024, // 100 KB
1024 * 1024, // 1 MB
}

func BenchmarkFSTree_HeadVsGet(b *testing.B) {
for _, size := range payloadSizes {
b.Run(generateSizeLabel(size), func(b *testing.B) {
Expand All @@ -39,39 +20,16 @@ func BenchmarkFSTree_HeadVsGet_Compressed(b *testing.B) {
}
}

func generateSizeLabel(size int) string {
switch {
case size == 0:
return "Empty"
case size < 1024:
return fmt.Sprintf("%dB", size)
case size < 1024*1024:
return fmt.Sprintf("%dKB", size/1024)
default:
return fmt.Sprintf("%dMB", size/(1024*1024))
}
}

func runHeadVsGetBenchmark(b *testing.B, payloadSize int, compressed bool) {
fsTree := fstree.New(fstree.WithPath(b.TempDir()))
fsTree := setupFSTree(b)

suffix := ""
if compressed {
compressConfig := &compression.Config{
Enabled: true,
}
require.NoError(b, compressConfig.Init())
fsTree.SetCompressor(compressConfig)
setupCompressor(b, fsTree)
suffix = "_Compressed"
}

require.NoError(b, fsTree.Open(false))
require.NoError(b, fsTree.Init())

obj := generateTestObject(payloadSize)
addr := object.AddressOf(obj)

require.NoError(b, fsTree.Put(addr, obj.Marshal()))
addr := prepareSingleObject(b, fsTree, payloadSize)

b.Run("Head"+suffix, func(b *testing.B) {
b.ResetTimer()
Expand All @@ -95,17 +53,3 @@ func runHeadVsGetBenchmark(b *testing.B, payloadSize int, compressed bool) {
}
})
}

func generateTestObject(payloadSize int) *objectSDK.Object {
obj := objecttest.Object()
if payloadSize > 0 {
payload := make([]byte, payloadSize)
_, _ = rand.Read(payload)
obj.SetPayload(payload)
} else {
obj.SetPayload(nil)
}
obj.SetPayloadSize(uint64(payloadSize))

return &obj
}
27 changes: 3 additions & 24 deletions pkg/local_object_storage/blobstor/fstree/head_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,14 @@ import (
"testing"

"github.com/nspcc-dev/neofs-node/pkg/core/object"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/compression"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/fstree"
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
"github.com/stretchr/testify/require"
)

func TestHeadStorage(t *testing.T) {
fsTree := fstree.New(fstree.WithPath(t.TempDir()))
require.NoError(t, fsTree.Open(false))
require.NoError(t, fsTree.Init())
fsTree := setupFSTree(t)

testObjects := func(t *testing.T, fsTree *fstree.FSTree, size int) {
obj := generateTestObject(size)
Expand Down Expand Up @@ -109,16 +106,8 @@ func TestHeadStorage(t *testing.T) {
})

t.Run("with compression", func(t *testing.T) {
compressConfig := &compression.Config{
Enabled: true,
}
require.NoError(t, compressConfig.Init())

fsComp := fstree.New(fstree.WithPath(t.TempDir()))
fsComp.SetCompressor(compressConfig)

require.NoError(t, fsComp.Open(false))
require.NoError(t, fsComp.Init())
fsComp := setupFSTree(t)
setupCompressor(t, fsComp)

for _, size := range payloadSizes {
t.Run("compressed_"+generateSizeLabel(size), func(t *testing.T) {
Expand All @@ -131,13 +120,3 @@ func TestHeadStorage(t *testing.T) {
}
})
}

func addAttribute(obj *objectSDK.Object, key, value string) {
var attr objectSDK.Attribute
attr.SetKey(key)
attr.SetValue(value)

attrs := obj.Attributes()
attrs = append(attrs, attr)
obj.SetAttributes(attrs...)
}
Loading
Loading