Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: extends computeRoots benchmark to cover larger square sizes and nmt tree #304

Merged
merged 11 commits into from
Mar 7, 2024
45 changes: 44 additions & 1 deletion datasquare_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package rsmt2d
import (
"crypto/sha256"
"fmt"
"math"
"reflect"
"testing"

"github.com/celestiaorg/merkletree"
"github.com/celestiaorg/nmt"
"github.com/stretchr/testify/assert"
)

Expand Down Expand Up @@ -401,7 +403,7 @@ func Test_setColSlice(t *testing.T) {
}
}

func BenchmarkEDSRoots(b *testing.B) {
func BenchmarkEDSRootsWithDefaultTree(b *testing.B) {
for i := 32; i < 513; i *= 2 {
square, err := newDataSquare(genRandDS(i*2, int(shareSize)), NewDefaultTree, shareSize)
if err != nil {
Expand All @@ -420,6 +422,47 @@ func BenchmarkEDSRoots(b *testing.B) {
}
}

func BenchmarkEDSRootsWithErasuredNMT(b *testing.B) {
ODSSizeByteUpperBound := 1024 * 1024 * 1024 // converting 512 MB to bytes
totalNumberOfShares := float64(ODSSizeByteUpperBound) / shareSize
// the closest power of 2 of the square root of
// the total number of shares
oDSShareSizeUpperBound := math.Pow(2, math.Ceil(math.Log2(math.Sqrt(
totalNumberOfShares))))
namespaceIDSize := 29

for i := 32; i <= int(oDSShareSizeUpperBound); i *= 2 {
// generate an EDS with i*2 X i*2 dimensions in terms of shares
// the generated EDS does not conform to celestia-app specs in terms
// of namespace version, also no erasure encoding takes place
// yet none of these should impact the benchmarking
ds := genRandSortedDS(i*2, shareSize, namespaceIDSize)

// a tree constructor for erasured nmt
treeConstructor := newErasuredNamespacedMerkleTreeConstructor(uint64(i*2),
nmt.NamespaceIDSize(namespaceIDSize), nmt.IgnoreMaxNamespace(true),
nmt.InitialCapacity(i*2))

square, err := newDataSquare(ds, treeConstructor, shareSize)
if err != nil {
b.Errorf("Failure to create square of size %d: %s", i, err)
}
b.Run(
fmt.Sprintf("%dx%dx%d ODS=%dMB, EDS=%dMB", i, i,
int(square.chunkSize),
i*i*shareSize/(1024*1024),
2*i*2*i*shareSize/(1024*1024)),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm kind of lost in the math here. Would it help readability to extract variables with names for these?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added more vars and clarifying comments in 9b26deb

func(b *testing.B) {
for n := 0; n < b.N; n++ {
square.resetRoots()
err := square.computeRoots()
assert.NoError(b, err)
}
},
)
}
}

func computeRowProof(ds *dataSquare, x uint, y uint) ([]byte, [][]byte, uint, uint, error) {
tree := ds.createTreeFn(Row, x)
data := ds.row(x)
Expand Down
2 changes: 1 addition & 1 deletion extendeddatacrossword_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ func createTestEdsWithNMT(t *testing.T, codec Codec, shareSize, namespaceSize in
edsWidth := 4 // number of shares per row/column in the extended data square
odsWidth := edsWidth / 2 // number of shares per row/column in the original data square

eds, err := ComputeExtendedDataSquare(shares, codec, newConstructor(uint64(odsWidth), nmt.NamespaceIDSize(namespaceSize)))
eds, err := ComputeExtendedDataSquare(shares, codec, newErasuredNamespacedMerkleTreeConstructor(uint64(odsWidth), nmt.NamespaceIDSize(namespaceSize)))
require.NoError(t, err)

return eds
Expand Down
13 changes: 13 additions & 0 deletions extendeddatasquare_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/json"
"fmt"
"reflect"
"sort"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -347,6 +348,18 @@ func genRandDS(width int, chunkSize int) [][]byte {
return ds
}

func genRandSortedDS(width int, chunkSize int, namespaceSize int) [][]byte {
ds := genRandDS(width, chunkSize)

// Sort the shares in the square based on their namespace
sort.Slice(ds, func(i, j int) bool {
// Compare only the first namespaceSize bytes
return bytes.Compare(ds[i][:namespaceSize], ds[j][:namespaceSize]) < 0
})

return ds
}

// TestFlattened_EDS tests that eds.Flattened() returns all the shares in the
// EDS. This function has the `_EDS` suffix to avoid a name collision with the
// TestFlattened.
Expand Down
8 changes: 5 additions & 3 deletions nmtwrapper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ type nmtTree interface {
// with an underlying NMT of namespace size `NamespaceSize` and with
// `ignoreMaxNamespace=true`. axisIndex is the index of the row or column that
// this tree is committing to. squareSize must be greater than zero.
func newErasuredNamespacedMerkleTree(squareSize uint64, axisIndex uint, options ...nmt.Option) erasuredNamespacedMerkleTree {
func newErasuredNamespacedMerkleTree(squareSize uint64, axisIndex uint,
options ...nmt.Option,
) erasuredNamespacedMerkleTree {
if squareSize == 0 {
panic("cannot create a erasuredNamespacedMerkleTree of squareSize == 0")
}
Expand All @@ -73,10 +75,10 @@ type constructor struct {
opts []nmt.Option
}

// newConstructor creates a tree constructor function as required by rsmt2d to
// newErasuredNamespacedMerkleTreeConstructor creates a tree constructor function as required by rsmt2d to
// calculate the data root. It creates that tree using the
// erasuredNamespacedMerkleTree.
func newConstructor(squareSize uint64, opts ...nmt.Option) TreeConstructorFn {
func newErasuredNamespacedMerkleTreeConstructor(squareSize uint64, opts ...nmt.Option) TreeConstructorFn {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a bit unrelated to this PR, but do we have the wrapper in both places, here and in app? https://github.com/celestiaorg/celestia-app/tree/main/pkg/wrapper

Copy link
Collaborator Author

@staheri14 staheri14 Mar 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question! Yes, we have, I did it in the past (inside the nmtwrapper_test file) to conduct some tests in the rsmt2d side without making circular dependency to the app.
PS: There is also an open issue #248 about moving the wrapper completely to the rsmt2d repo.

return constructor{
squareSize: squareSize,
opts: opts,
Expand Down
Loading