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

Problem: memiavl zero-copy don't work with inter-block cache #1035

Merged
merged 4 commits into from
May 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
15 changes: 13 additions & 2 deletions app/config/config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package config

import "github.com/evmos/ethermint/server/config"
import (
"github.com/crypto-org-chain/cronos/memiavl"
"github.com/evmos/ethermint/server/config"
)

const DefaultCacheSize = 1000

type Config struct {
config.Config
Expand All @@ -21,8 +26,14 @@ 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,
SnapshotInterval: memiavl.DefaultSnapshotInterval,
ZeroCopy: true,
}
}
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
1 change: 1 addition & 0 deletions memiavl/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ func TestLoadVersion(t *testing.T) {
require.NoError(t, err)
})
}
require.NoError(t, db.WaitAsyncCommit())

for v, expItems := range ExpectItems {
if v == 0 {
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)

Check failure

Code scanning / gosec

Potential integer overflow by integer type conversion

Potential integer overflow by integer type conversion
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