Skip to content

Commit

Permalink
Problem: memiavl zero-copy don't work with inter-block cache
Browse files Browse the repository at this point in the history
Solution:
- ignore the inter-block cache silently
- roll it's own cache in memiavl trees

Update CHANGELOG.md

Signed-off-by: yihuang <[email protected]>
  • Loading branch information
yihuang committed May 26, 2023
1 parent dfa887d commit 9a21b4e
Show file tree
Hide file tree
Showing 18 changed files with 99 additions and 82 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
- [#1027](https://github.com/crypto-org-chain/cronos/pull/1027) Integrate local state-sync commands.
- [#1029](https://github.com/crypto-org-chain/cronos/pull/1029) Change config `async-commit` to `async-commit-buffer`, make the channel size configurable.
- [#1034](https://github.com/crypto-org-chain/cronos/pull/1034) Support memiavl snapshot strategy configuration.
- [#1035](https://github.com/crypto-org-chain/cronos/pull/1035) Support caching in memiavl directly, ignore inter-block cache silently.

*April 13, 2023*

Expand Down
8 changes: 7 additions & 1 deletion app/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package config

import "github.com/evmos/ethermint/server/config"

const DefaultCacheSize = 1000

type Config struct {
config.Config

Expand All @@ -21,8 +23,12 @@ type MemIAVLConfig struct {
SnapshotKeepRecent uint32 `mapstructure:"snapshot-keep-recent"`
// SnapshotInterval defines the block interval the memiavl snapshot is taken, default to 1000.
SnapshotInterval uint32 `mapstructure:"snapshot-interval"`
// CacheSize defines the size of the cache for each memiavl store.
CacheSize int `mapstructure:"cache-size"`
}

func DefaultMemIAVLConfig() MemIAVLConfig {
return MemIAVLConfig{}
return MemIAVLConfig{
CacheSize: DefaultCacheSize,
}
}
3 changes: 3 additions & 0 deletions app/config/toml.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,7 @@ snapshot-keep-recent = {{ .MemIAVL.SnapshotKeepRecent }}
# SnapshotInterval defines the block interval the memiavl snapshot is taken, default to 1000.
snapshot-interval = {{ .MemIAVL.SnapshotInterval }}
# CacheSize defines the size of the cache for each memiavl store, default to 1000.
cache-size = {{ .MemIAVL.CacheSize }}
`
2 changes: 2 additions & 0 deletions app/memiavl.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const (
FlagZeroCopy = "memiavl.zero-copy"
FlagSnapshotKeepRecent = "memiavl.snapshot-keep-recent"
FlagSnapshotInterval = "memiavl.snapshot-interval"
FlagCacheSize = "memiavl.cache-size"
)

func SetupMemIAVL(logger log.Logger, homePath string, appOpts servertypes.AppOptions, baseAppOptions []func(*baseapp.BaseApp)) []func(*baseapp.BaseApp) {
Expand All @@ -34,6 +35,7 @@ func SetupMemIAVL(logger log.Logger, homePath string, appOpts servertypes.AppOpt
SnapshotInterval: cast.ToUint32(appOpts.Get(FlagSnapshotInterval)),
// make sure a few queryable states even with pruning="nothing", needed for ibc relayer to work.
MinQueryStates: 3,
CacheSize: cast.ToInt(appOpts.Get(FlagCacheSize)),
})
baseAppOptions = append([]func(*baseapp.BaseApp){setCMS(cms)}, baseAppOptions...)
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/cosmos/cosmos-sdk v0.46.13-0.20230513091001-5472fb5995a0
github.com/cosmos/gogoproto v1.4.7
github.com/cosmos/ibc-go/v5 v5.2.1
github.com/crypto-org-chain/cronos/memiavl v0.0.1
github.com/crypto-org-chain/cronos/store v0.0.0
github.com/crypto-org-chain/cronos/versiondb v0.0.0
github.com/ethereum/go-ethereum v1.10.26
Expand Down Expand Up @@ -79,7 +80,6 @@ require (
github.com/cosmos/iavl v0.19.6-0.20230410112350-e1e212a3a3aa // indirect
github.com/cosmos/ledger-cosmos-go v0.12.2 // indirect
github.com/creachadair/taskgroup v0.3.2 // indirect
github.com/crypto-org-chain/cronos/memiavl v0.0.1 // indirect
github.com/danieljoos/wincred v1.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deckarep/golang-set v1.8.0 // indirect
Expand Down
1 change: 0 additions & 1 deletion integration_tests/configs/default.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
staked: '1000000000000000000stake',
mnemonic: '${VALIDATOR1_MNEMONIC}',
'app-config': {
'inter-block-cache': false,
memiavl: {
enable: true,
'zero-copy': true,
Expand Down
6 changes: 3 additions & 3 deletions memiavl/benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func BenchmarkRandomGet(b *testing.B) {
targetValue := items[500].value
targetItem := itemT{key: targetKey}

tree := New()
tree := New(0)
for _, item := range items {
tree.set(item.key, item.value)
}
Expand All @@ -39,7 +39,7 @@ func BenchmarkRandomGet(b *testing.B) {
snapshot, err := OpenSnapshot(snapshotDir)
require.NoError(b, err)
defer snapshot.Close()
diskTree := NewFromSnapshot(snapshot, true)
diskTree := NewFromSnapshot(snapshot, true, 0)

require.Equal(b, targetValue, tree.Get(targetKey))
require.Equal(b, targetValue, diskTree.Get(targetKey))
Expand Down Expand Up @@ -170,7 +170,7 @@ func BenchmarkRandomSet(b *testing.B) {
b.ResetTimer()
b.Run("memiavl", func(b *testing.B) {
for i := 0; i < b.N; i++ {
tree := New()
tree := New(0)
for _, item := range items {
tree.set(item.key, item.value)
}
Expand Down
20 changes: 11 additions & 9 deletions memiavl/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ type Options struct {
ZeroCopy bool
// for ibc relayer to work, we need to make sure at least a few queryable states exists even with pruning="nothing" setting.
MinQueryStates int
// CacheSize defines the cache's max entry size for each memiavl store.
CacheSize int
}

const (
Expand Down Expand Up @@ -113,13 +115,13 @@ func Load(dir string, opts Options) (*DB, error) {
}

path := filepath.Join(dir, snapshotName)
mtree, err := LoadMultiTree(path, opts.ZeroCopy)
mtree, err := LoadMultiTree(path, opts.ZeroCopy, opts.CacheSize)
if err != nil {
if opts.CreateIfMissing && os.IsNotExist(err) {
if err := initEmptyDB(dir, opts.InitialVersion); err != nil {
return nil, err
}
mtree, err = LoadMultiTree(path, opts.ZeroCopy)
mtree, err = LoadMultiTree(path, opts.ZeroCopy, opts.CacheSize)
}
if err != nil {
return nil, err
Expand Down Expand Up @@ -410,11 +412,11 @@ func (db *DB) Copy() *DB {
db.mtx.Lock()
defer db.mtx.Unlock()

return db.copy()
return db.copy(db.cacheSize)
}

func (db *DB) copy() *DB {
mtree := db.MultiTree.Copy()
func (db *DB) copy(cacheSize int) *DB {
mtree := db.MultiTree.Copy(cacheSize)
return &DB{
MultiTree: *mtree,
logger: db.logger,
Expand Down Expand Up @@ -447,7 +449,7 @@ func (db *DB) Reload() error {
}

func (db *DB) reload() error {
mtree, err := LoadMultiTree(currentPath(db.dir), db.zeroCopy)
mtree, err := LoadMultiTree(currentPath(db.dir), db.zeroCopy, db.cacheSize)
if err != nil {
return err
}
Expand Down Expand Up @@ -503,7 +505,7 @@ func (db *DB) rewriteSnapshotBackground() error {
ch := make(chan snapshotResult)
db.snapshotRewriteChan = ch

cloned := db.copy()
cloned := db.copy(0)
wal := db.wal
go func() {
defer close(ch)
Expand All @@ -514,7 +516,7 @@ func (db *DB) rewriteSnapshotBackground() error {
return
}
cloned.logger.Info("finished rewriting snapshot", "version", cloned.Version())
mtree, err := LoadMultiTree(currentPath(cloned.dir), db.zeroCopy)
mtree, err := LoadMultiTree(currentPath(cloned.dir), cloned.zeroCopy, 0)
if err != nil {
ch <- snapshotResult{err: err}
return
Expand Down Expand Up @@ -700,7 +702,7 @@ func walPath(root string) string {
// current -> snapshot-0
// ```
func initEmptyDB(dir string, initialVersion uint32) error {
tmp := NewEmptyMultiTree(initialVersion)
tmp := NewEmptyMultiTree(initialVersion, 0)
snapshotDir := snapshotName(0)
if err := tmp.WriteSnapshot(filepath.Join(dir, snapshotDir)); err != nil {
return err
Expand Down
4 changes: 2 additions & 2 deletions memiavl/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ require (
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d
github.com/ledgerwatch/erigon-lib v0.0.0-20230210071639-db0e7ed11263
github.com/stretchr/testify v1.8.2
github.com/tendermint/tendermint v0.34.27
github.com/tendermint/tm-db v0.6.7
github.com/tidwall/btree v1.5.0
github.com/tidwall/wal v1.1.7
golang.org/x/exp v0.0.0-20230206171751-46f607a40771
golang.org/x/sync v0.1.0
golang.org/x/sys v0.6.0
)

require (
Expand Down Expand Up @@ -66,7 +68,6 @@ require (
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
github.com/tendermint/go-amino v0.16.0 // indirect
github.com/tendermint/tendermint v0.34.27 // indirect
github.com/tidwall/gjson v1.10.2 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
Expand All @@ -78,7 +79,6 @@ require (
go.uber.org/atomic v1.10.0 // indirect
golang.org/x/crypto v0.6.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/text v0.8.0 // indirect
google.golang.org/genproto v0.0.0-20230202175211-008b39050e57 // indirect
google.golang.org/grpc v1.53.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions memiavl/iterator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
)

func TestIterator(t *testing.T) {
tree := NewEmptyTree(0)
tree := New(0)
require.Equal(t, ExpectItems[0], collectIter(tree.Iterator(nil, nil, true)))

for _, changes := range ChangeSets {
Expand All @@ -20,7 +20,7 @@ func TestIterator(t *testing.T) {
}

func TestIteratorRange(t *testing.T) {
tree := NewEmptyTree(0)
tree := New(0)
for _, changes := range ChangeSets[:6] {
_, _, err := tree.ApplyChangeSet(changes, true)
require.NoError(t, err)
Expand Down
17 changes: 10 additions & 7 deletions memiavl/multitree.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ type MultiTree struct {
// it always corresponds to the wal entry with index 1.
initialVersion uint32

zeroCopy bool
zeroCopy bool
cacheSize int

trees []namedTree
treesByName map[string]int // reversed index of the trees
Expand All @@ -55,15 +56,16 @@ type MultiTree struct {
metadata MultiTreeMetadata
}

func NewEmptyMultiTree(initialVersion uint32) *MultiTree {
func NewEmptyMultiTree(initialVersion uint32, cacheSize int) *MultiTree {
return &MultiTree{
initialVersion: initialVersion,
treesByName: make(map[string]int),
zeroCopy: true,
cacheSize: cacheSize,
}
}

func LoadMultiTree(dir string, zeroCopy bool) (*MultiTree, error) {
func LoadMultiTree(dir string, zeroCopy bool, cacheSize int) (*MultiTree, error) {
// load commit info
bz, err := os.ReadFile(filepath.Join(dir, MetadataFileName))
if err != nil {
Expand Down Expand Up @@ -97,7 +99,7 @@ func LoadMultiTree(dir string, zeroCopy bool) (*MultiTree, error) {
if err != nil {
return nil, err
}
treeMap[name] = NewFromSnapshot(snapshot, zeroCopy)
treeMap[name] = NewFromSnapshot(snapshot, zeroCopy, cacheSize)
}

sort.Strings(treeNames)
Expand All @@ -116,6 +118,7 @@ func LoadMultiTree(dir string, zeroCopy bool) (*MultiTree, error) {
lastCommitInfo: *metadata.CommitInfo,
metadata: metadata,
zeroCopy: zeroCopy,
cacheSize: cacheSize,
}
// initial version is nesserary for wal index conversion
mtree.setInitialVersion(metadata.InitialVersion)
Expand Down Expand Up @@ -164,11 +167,11 @@ func (t *MultiTree) SetZeroCopy(zeroCopy bool) {
}

// Copy returns a snapshot of the tree which won't be corrupted by further modifications on the main tree.
func (t *MultiTree) Copy() *MultiTree {
func (t *MultiTree) Copy(cacheSize int) *MultiTree {
trees := make([]namedTree, len(t.trees))
treesByName := make(map[string]int, len(t.trees))
for i, entry := range t.trees {
tree := entry.tree.Copy()
tree := entry.tree.Copy(cacheSize)
trees[i] = namedTree{tree: tree, name: entry.name}
treesByName[entry.name] = i
}
Expand Down Expand Up @@ -226,7 +229,7 @@ func (t *MultiTree) ApplyUpgrades(upgrades []*TreeNameUpgrade) error {
t.trees[i].name = upgrade.Name
default:
// add tree
tree := NewWithInitialVersion(uint32(nextVersion(t.Version(), t.initialVersion)))
tree := NewWithInitialVersion(uint32(nextVersion(t.Version(), t.initialVersion)), t.cacheSize)
t.trees = append(t.trees, namedTree{tree: tree, name: upgrade.Name})
}
}
Expand Down
4 changes: 2 additions & 2 deletions memiavl/proof_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestProofs(t *testing.T) {
}

tmpDir := t.TempDir()
tree := NewEmptyTree(0)
tree := New(0)

for i, tc := range testCases {
t.Run(strconv.Itoa(i), func(t *testing.T) {
Expand All @@ -43,7 +43,7 @@ func TestProofs(t *testing.T) {
require.NoError(t, tree.WriteSnapshot(tmpDir, false))
snapshot, err := OpenSnapshot(tmpDir)
require.NoError(t, err)
ptree := NewFromSnapshot(snapshot, true)
ptree := NewFromSnapshot(snapshot, true, 0)
defer ptree.Close()

proof, err = ptree.GetMembershipProof(tc.existKey)
Expand Down
10 changes: 5 additions & 5 deletions memiavl/snapshot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (

func TestSnapshotEncodingRoundTrip(t *testing.T) {
// setup test tree
tree := NewEmptyTree(0)
tree := New(0)
for _, changes := range ChangeSets[:len(ChangeSets)-1] {
_, _, err := tree.ApplyChangeSet(changes, true)
require.NoError(t, err)
Expand All @@ -24,7 +24,7 @@ func TestSnapshotEncodingRoundTrip(t *testing.T) {
snapshot, err := OpenSnapshot(snapshotDir)
require.NoError(t, err)

tree2 := NewFromSnapshot(snapshot, true)
tree2 := NewFromSnapshot(snapshot, true, 0)

require.Equal(t, tree.Version(), tree2.Version())
require.Equal(t, tree.RootHash(), tree2.RootHash())
Expand All @@ -40,7 +40,7 @@ func TestSnapshotEncodingRoundTrip(t *testing.T) {
// test modify tree loaded from snapshot
snapshot, err = OpenSnapshot(snapshotDir)
require.NoError(t, err)
tree3 := NewFromSnapshot(snapshot, true)
tree3 := NewFromSnapshot(snapshot, true, 0)
hash, v, err := tree3.ApplyChangeSet(ChangeSets[len(ChangeSets)-1], true)
require.NoError(t, err)
require.Equal(t, RefHashes[len(ChangeSets)-1], hash)
Expand All @@ -60,7 +60,7 @@ func TestSnapshotExport(t *testing.T) {
}

// setup test tree
tree := NewEmptyTree(0)
tree := New(0)
for _, changes := range ChangeSets[:3] {
_, _, err := tree.ApplyChangeSet(changes, true)
require.NoError(t, err)
Expand Down Expand Up @@ -88,7 +88,7 @@ func TestSnapshotExport(t *testing.T) {

func TestSnapshotImportExport(t *testing.T) {
// setup test tree
tree := NewEmptyTree(0)
tree := New(0)
for _, changes := range ChangeSets {
_, _, err := tree.ApplyChangeSet(changes, true)
require.NoError(t, err)
Expand Down
Loading

0 comments on commit 9a21b4e

Please sign in to comment.