Skip to content

Commit

Permalink
MerkleDB -- add eviction batch size config (ava-labs#1586)
Browse files Browse the repository at this point in the history
  • Loading branch information
danlaine committed Jun 6, 2023
1 parent aed31ae commit 268f5a9
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 130 deletions.
26 changes: 15 additions & 11 deletions x/merkledb/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ import (
)

const (
RootPath = EmptyPath
evictionBatchSize = 100
RootPath = EmptyPath
// TODO: name better
rebuildViewSizeFractionOfCacheSize = 50
minRebuildViewSizePerCommit = 1000
Expand Down Expand Up @@ -116,6 +115,9 @@ type MerkleDB interface {
}

type Config struct {
// The number of nodes that are evicted from the cache and written to
// disk at a time.
EvictionBatchSize int
// The number of changes to the database that we store in memory in order to
// serve change proofs.
HistoryLength int
Expand Down Expand Up @@ -144,8 +146,9 @@ type merkleDB struct {
metadataDB database.Database

// If a value is nil, the corresponding key isn't in the trie.
nodeCache onEvictCache[path, *node]
onEvictionErr utils.Atomic[error]
nodeCache onEvictCache[path, *node]
onEvictionErr utils.Atomic[error]
evictionBatchSize int

// Stores change lists. Used to serve change proofs and construct
// historical views of the trie.
Expand All @@ -172,12 +175,13 @@ func newDatabase(
metrics merkleMetrics,
) (*merkleDB, error) {
trieDB := &merkleDB{
metrics: metrics,
nodeDB: prefixdb.New(nodePrefix, db),
metadataDB: prefixdb.New(metadataPrefix, db),
history: newTrieHistory(config.HistoryLength),
tracer: config.Tracer,
childViews: make([]*trieView, 0, defaultPreallocationSize),
metrics: metrics,
nodeDB: prefixdb.New(nodePrefix, db),
metadataDB: prefixdb.New(metadataPrefix, db),
history: newTrieHistory(config.HistoryLength),
tracer: config.Tracer,
childViews: make([]*trieView, 0, defaultPreallocationSize),
evictionBatchSize: config.EvictionBatchSize,
}

// Note: trieDB.OnEviction is responsible for writing intermediary nodes to
Expand Down Expand Up @@ -757,7 +761,7 @@ func (db *merkleDB) onEviction(n *node) error {
// just [n], so that we don't immediately evict and write another
// node, because each time this method is called we do a disk write.
var err error
for removedCount := 0; removedCount < evictionBatchSize; removedCount++ {
for removedCount := 0; removedCount < db.evictionBatchSize; removedCount++ {
_, n, exists := db.nodeCache.removeOldest()
if !exists {
// The cache is empty.
Expand Down
49 changes: 20 additions & 29 deletions x/merkledb/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"strconv"
"testing"

"github.com/prometheus/client_golang/prometheus"
"github.com/stretchr/testify/require"

"github.com/ava-labs/avalanchego/database"
Expand All @@ -26,6 +27,16 @@ func newNoopTracer() trace.Tracer {
return tracer
}

func newDefaultConfig() Config {
return Config{
EvictionBatchSize: 100,
HistoryLength: 100,
NodeCacheSize: 1_000,
Reg: prometheus.NewRegistry(),
Tracer: newNoopTracer(),
}
}

func Test_MerkleDB_Get_Safety(t *testing.T) {
db, err := getBasicDB()
require.NoError(t, err)
Expand Down Expand Up @@ -86,11 +97,7 @@ func Test_MerkleDB_DB_Load_Root_From_DB(t *testing.T) {
db, err := New(
context.Background(),
rdb,
Config{
Tracer: newNoopTracer(),
HistoryLength: 100,
NodeCacheSize: 100,
},
newDefaultConfig(),
)
require.NoError(err)

Expand All @@ -112,11 +119,7 @@ func Test_MerkleDB_DB_Load_Root_From_DB(t *testing.T) {
db, err = New(
context.Background(),
rdb,
Config{
Tracer: newNoopTracer(),
HistoryLength: 100,
NodeCacheSize: 100,
},
newDefaultConfig(),
)
require.NoError(err)
reloadedRoot, err := db.GetMerkleRoot(context.Background())
Expand All @@ -132,14 +135,13 @@ func Test_MerkleDB_DB_Rebuild(t *testing.T) {

initialSize := 10_000

config := newDefaultConfig()
config.NodeCacheSize = initialSize

db, err := New(
context.Background(),
rdb,
Config{
Tracer: newNoopTracer(),
HistoryLength: 100,
NodeCacheSize: initialSize,
},
config,
)
require.NoError(err)

Expand Down Expand Up @@ -167,10 +169,7 @@ func Test_MerkleDB_Failed_Batch_Commit(t *testing.T) {
db, err := New(
context.Background(),
memDB,
Config{
Tracer: newNoopTracer(),
HistoryLength: 300,
},
newDefaultConfig(),
)
require.NoError(t, err)

Expand All @@ -190,11 +189,7 @@ func Test_MerkleDB_Value_Cache(t *testing.T) {
db, err := New(
context.Background(),
memDB,
Config{
Tracer: newNoopTracer(),
HistoryLength: 300,
NodeCacheSize: minCacheSize,
},
newDefaultConfig(),
)
require.NoError(t, err)

Expand Down Expand Up @@ -815,11 +810,7 @@ func runRandDBTest(require *require.Assertions, r *rand.Rand, rt randTest) {
dbTrie, err := newDatabase(
context.Background(),
memdb.New(),
Config{
Tracer: newNoopTracer(),
HistoryLength: 0,
NodeCacheSize: minCacheSize,
},
newDefaultConfig(),
&mockMetrics{},
)
require.NoError(err)
Expand Down
24 changes: 14 additions & 10 deletions x/sync/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"time"

"github.com/golang/mock/gomock"
"github.com/prometheus/client_golang/prometheus"

"github.com/stretchr/testify/require"

Expand All @@ -27,6 +28,16 @@ import (
syncpb "github.com/ava-labs/avalanchego/proto/pb/sync"
)

func newDefaultDBConfig() merkledb.Config {
return merkledb.Config{
EvictionBatchSize: 100,
HistoryLength: defaultRequestKeyLimit,
NodeCacheSize: defaultRequestKeyLimit,
Reg: prometheus.NewRegistry(),
Tracer: newNoopTracer(),
}
}

func sendRangeRequest(
t *testing.T,
db SyncableDB,
Expand Down Expand Up @@ -377,21 +388,14 @@ func TestGetChangeProof(t *testing.T) {
trieDB, err := merkledb.New(
context.Background(),
memdb.New(),
merkledb.Config{
Tracer: newNoopTracer(),
HistoryLength: defaultRequestKeyLimit,
NodeCacheSize: defaultRequestKeyLimit,
},
newDefaultDBConfig(),
)
require.NoError(t, err)

verificationDB, err := merkledb.New(
context.Background(),
memdb.New(),
merkledb.Config{
Tracer: newNoopTracer(),
HistoryLength: defaultRequestKeyLimit,
NodeCacheSize: defaultRequestKeyLimit,
},
newDefaultDBConfig(),
)
require.NoError(t, err)
startRoot, err := trieDB.GetMerkleRoot(context.Background())
Expand Down

0 comments on commit 268f5a9

Please sign in to comment.