From fa9e62a1ef24f151c00fde8ec7960be237518c2c Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Thu, 24 Aug 2023 14:29:32 +0200 Subject: [PATCH] Add GetLedgerEntry benchmark and optimize it slightly --- cmd/soroban-rpc/internal/db/ledgerentry.go | 10 ++- .../internal/db/ledgerentry_test.go | 63 +++++++++++++++++-- 2 files changed, 66 insertions(+), 7 deletions(-) diff --git a/cmd/soroban-rpc/internal/db/ledgerentry.go b/cmd/soroban-rpc/internal/db/ledgerentry.go index 366373eb3f..82a3f8c3d4 100644 --- a/cmd/soroban-rpc/internal/db/ledgerentry.go +++ b/cmd/soroban-rpc/internal/db/ledgerentry.go @@ -292,9 +292,13 @@ func (l *ledgerEntryReadTx) GetLedgerEntries(includeExpired bool, keys ...xdr.Le result := make([]LedgerKeyAndEntry, 0, len(rawResult)) - latestClosedLedger, err := l.GetLatestLedgerSequence() - if err != nil { - return nil, err + var latestClosedLedger uint32 + if !includeExpired { + // We only need the latest ledger when excluding expired entries + latestClosedLedger, err = l.GetLatestLedgerSequence() + if err != nil { + return nil, err + } } for encodedKey, key := range encodedKeyToKey { encodedEntry, ok := rawResult[encodedKey] diff --git a/cmd/soroban-rpc/internal/db/ledgerentry_test.go b/cmd/soroban-rpc/internal/db/ledgerentry_test.go index ede854181a..d58cd7d873 100644 --- a/cmd/soroban-rpc/internal/db/ledgerentry_test.go +++ b/cmd/soroban-rpc/internal/db/ledgerentry_test.go @@ -736,6 +736,65 @@ forloop: } +func benchmarkLedgerEntry(b *testing.B, cached bool, includeExpired bool) { + db := NewTestDB(b) + keyUint32 := xdr.Uint32(0) + data := xdr.ContractDataEntry{ + Contract: xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeContract, + ContractId: &xdr.Hash{0xca, 0xfe}, + }, + Key: xdr.ScVal{ + Type: xdr.ScValTypeScvU32, + U32: &keyUint32, + }, + Durability: xdr.ContractDataDurabilityPersistent, + Body: xdr.ContractDataEntryBody{ + BodyType: xdr.ContractEntryBodyTypeDataEntry, + Data: &xdr.ContractDataEntryData{ + Val: xdr.ScVal{ + Type: xdr.ScValTypeScvU32, + U32: &keyUint32, + }, + }, + }, + ExpirationLedgerSeq: math.MaxUint32, + } + key, entry := getContractDataLedgerEntry(b, data) + tx, err := NewReadWriter(db, 150, 15).NewTx(context.Background()) + assert.NoError(b, err) + assert.NoError(b, tx.LedgerEntryWriter().UpsertLedgerEntry(entry)) + assert.NoError(b, tx.Commit(2)) + reader := NewLedgerEntryReader(db) + const numQueriesPerOp = 3500 + b.ResetTimer() + b.StopTimer() + for i := 0; i < b.N; i++ { + var readTx LedgerEntryReadTx + var err error + if cached { + readTx, err = reader.NewCachedTx(context.Background()) + } else { + readTx, err = reader.NewTx(context.Background()) + } + assert.NoError(b, err) + for i := 0; i < numQueriesPerOp; i++ { + b.StartTimer() + found, _, err := GetLedgerEntry(readTx, includeExpired, key) + b.StopTimer() + assert.NoError(b, err) + assert.True(b, found) + } + assert.NoError(b, readTx.Done()) + } +} + +func BenchmarkGetLedgerEntry(b *testing.B) { + b.Run("With cache, include expired", func(b *testing.B) { benchmarkLedgerEntry(b, true, true) }) + b.Run("With cache, exclude expired", func(b *testing.B) { benchmarkLedgerEntry(b, true, false) }) + b.Run("Without cache, exclude expired", func(b *testing.B) { benchmarkLedgerEntry(b, false, false) }) +} + func BenchmarkLedgerUpdate(b *testing.B) { db := NewTestDB(b) keyUint32 := xdr.Uint32(0) @@ -773,7 +832,6 @@ func BenchmarkLedgerUpdate(b *testing.B) { } assert.NoError(b, tx.Commit(uint32(i+1))) } - b.StopTimer() } func NewTestDB(tb testing.TB) *DB { @@ -783,9 +841,6 @@ func NewTestDB(tb testing.TB) *DB { if err != nil { assert.NoError(tb, db.Close()) } - var ver []string - assert.NoError(tb, db.SelectRaw(context.Background(), &ver, "SELECT sqlite_version()")) - tb.Logf("using sqlite version: %v", ver) tb.Cleanup(func() { assert.NoError(tb, db.Close()) })