From cc3fb47fd9a6d34b3f0091297c4457982a3b766f Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Tue, 25 Jul 2023 18:04:02 +0400 Subject: [PATCH 1/2] blobovnicza: Add benchmark to test different tree settings goos: linux goarch: amd64 pkg: github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/blobovniczatree cpu: Intel(R) Core(TM) i5-10210U CPU @ 1.60GHz BenchmarkBlobovniczas_Put/tree=1x0-8 61 19747177 ns/op 33398 B/op 77 allocs/op BenchmarkBlobovniczas_Put/tree=10x0-8 60 18623677 ns/op 33600 B/op 77 allocs/op BenchmarkBlobovniczas_Put/tree=2x2-8 56 20861449 ns/op 36191 B/op 112 allocs/op BenchmarkBlobovniczas_Put/tree=4x4-8 43 25999988 ns/op 38511 B/op 182 allocs/op Signed-off-by: Leonard Lyubich --- .../blobstor/blobovniczatree/put_test.go | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/put_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/put_test.go index 077267f12e..cd928ec054 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/put_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/put_test.go @@ -1,6 +1,9 @@ package blobovniczatree_test import ( + "crypto/rand" + "errors" + "fmt" "testing" . "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/blobovniczatree" @@ -37,3 +40,68 @@ func TestSingleDir(t *testing.T) { }) require.NoError(t, err) } + +func benchmarkPutMN(b *testing.B, depth, width uint64) { + nBlobovniczas := uint64(1) + for i := uint64(1); i <= depth+1; i++ { + nBlobovniczas *= width + } + + const objSizeLimit = 4 << 10 + const fullSizeLimit = 100 << 20 + + bbcz := NewBlobovniczaTree( + WithRootPath(b.TempDir()), + WithObjectSizeLimit(objSizeLimit), + WithBlobovniczaSize(fullSizeLimit/nBlobovniczas), + WithBlobovniczaShallowWidth(width), + WithBlobovniczaShallowDepth(depth), + ) + + require.NoError(b, bbcz.Open(false)) + b.Cleanup(func() { _ = bbcz.Close() }) + require.NoError(b, bbcz.Init()) + + prm := common.PutPrm{ + RawData: make([]byte, objSizeLimit), + } + + rand.Read(prm.RawData) + + b.ReportAllocs() + b.ResetTimer() + + var err error + + for i := 0; i < b.N; i++ { + b.StopTimer() + prm.Address = oidtest.Address() + b.StartTimer() + + _, err = bbcz.Put(prm) + + b.StopTimer() + if err != nil { + if errors.Is(err, common.ErrNoSpace) { + break + } + require.NoError(b, err) + } + b.StartTimer() + } +} + +func BenchmarkBlobovniczas_Put(b *testing.B) { + for _, testCase := range []struct { + width, depth uint64 + }{ + {1, 0}, + {10, 0}, + {2, 2}, + {4, 4}, + } { + b.Run(fmt.Sprintf("tree=%dx%d", testCase.width, testCase.depth), func(b *testing.B) { + benchmarkPutMN(b, testCase.depth, testCase.width) + }) + } +} From d22c757624fc19a31fa098da35d6179090c87e70 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Wed, 26 Jul 2023 18:33:05 +0400 Subject: [PATCH 2/2] blobovnicza: Extend write benchmark with parallel runs goos: linux goarch: amd64 pkg: github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/blobovniczatree cpu: Intel(R) Core(TM) i5-10210U CPU @ 1.60GHz BenchmarkBlobovniczas_Put/tree=1x0_parallel-8 50 25138722 ns/op 503770 B/op 718 allocs/op BenchmarkBlobovniczas_Put/tree=10x0_parallel-8 49 24535074 ns/op 502562 B/op 723 allocs/op BenchmarkBlobovniczas_Put/tree=2x2_parallel-8 30 53013230 ns/op 630769 B/op 1748 allocs/op BenchmarkBlobovniczas_Put/tree=4x4_parallel-8 19 54977576 ns/op 762231 B/op 3308 allocs/op Signed-off-by: Leonard Lyubich --- .../blobstor/blobovniczatree/put_test.go | 49 +++++++++++++------ 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/put_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/put_test.go index cd928ec054..51ded67178 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/put_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/put_test.go @@ -4,6 +4,7 @@ import ( "crypto/rand" "errors" "fmt" + "sync" "testing" . "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/blobovniczatree" @@ -41,7 +42,7 @@ func TestSingleDir(t *testing.T) { require.NoError(t, err) } -func benchmarkPutMN(b *testing.B, depth, width uint64) { +func benchmarkPutMN(b *testing.B, depth, width uint64, parallel bool) { nBlobovniczas := uint64(1) for i := uint64(1); i <= depth+1; i++ { nBlobovniczas *= width @@ -68,27 +69,40 @@ func benchmarkPutMN(b *testing.B, depth, width uint64) { rand.Read(prm.RawData) - b.ReportAllocs() - b.ResetTimer() + var wg sync.WaitGroup - var err error + f := func(prm common.PutPrm) { + defer wg.Done() - for i := 0; i < b.N; i++ { - b.StopTimer() - prm.Address = oidtest.Address() - b.StartTimer() + var err error - _, err = bbcz.Put(prm) + for i := 0; i < b.N; i++ { + prm.Address = oidtest.Address() - b.StopTimer() - if err != nil { - if errors.Is(err, common.ErrNoSpace) { - break + _, err = bbcz.Put(prm) + if err != nil { + if errors.Is(err, common.ErrNoSpace) { + break + } + require.NoError(b, err) } - require.NoError(b, err) } - b.StartTimer() } + + nRoutine := 1 + if parallel { + nRoutine = 20 + } + + b.ReportAllocs() + b.ResetTimer() + + for j := 0; j < nRoutine; j++ { + wg.Add(1) + go f(prm) + } + + wg.Wait() } func BenchmarkBlobovniczas_Put(b *testing.B) { @@ -101,7 +115,10 @@ func BenchmarkBlobovniczas_Put(b *testing.B) { {4, 4}, } { b.Run(fmt.Sprintf("tree=%dx%d", testCase.width, testCase.depth), func(b *testing.B) { - benchmarkPutMN(b, testCase.depth, testCase.width) + benchmarkPutMN(b, testCase.depth, testCase.width, false) + }) + b.Run(fmt.Sprintf("tree=%dx%d_parallel", testCase.width, testCase.depth), func(b *testing.B) { + benchmarkPutMN(b, testCase.depth, testCase.width, true) }) } }