forked from cerc-io/laconicd-deprecated
Merge pull request #464 from AlexeyAkhunov/master
R4R: Add Caching to Store Database
This commit is contained in:
commit
cd90daaadf
@ -59,6 +59,8 @@ type Database struct {
|
||||
// EXTCODESIZE calls.
|
||||
codeSizeCache *lru.Cache
|
||||
|
||||
storeCache *lru.Cache
|
||||
|
||||
Tracing bool
|
||||
}
|
||||
|
||||
@ -66,7 +68,7 @@ type Database struct {
|
||||
// implements Ethereum's state.Database interface. An error is returned if the
|
||||
// latest state failed to load. The underlying storage structure is defined by
|
||||
// the Cosmos SDK IAVL tree.
|
||||
func NewDatabase(stateDB, codeDB dbm.DB) (*Database, error) {
|
||||
func NewDatabase(stateDB, codeDB dbm.DB, storeCacheSize int) (*Database, error) {
|
||||
// Initialize an implementation of Ethereum state.Database and create a
|
||||
// Cosmos SDK multi-store.
|
||||
db := &Database{
|
||||
@ -93,7 +95,13 @@ func NewDatabase(stateDB, codeDB dbm.DB) (*Database, error) {
|
||||
db.codeDB = codeDB
|
||||
db.ethTrieDB = ethtrie.NewDatabase(&core.EthereumDB{CodeDB: codeDB})
|
||||
|
||||
db.codeSizeCache, _ = lru.New(codeSizeCacheSize)
|
||||
var err error
|
||||
if db.codeSizeCache, err = lru.New(codeSizeCacheSize); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if db.storeCache, err = lru.New(storeCacheSize); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return db, nil
|
||||
}
|
||||
@ -133,6 +141,7 @@ func (db *Database) OpenTrie(root ethcmn.Hash) (ethstate.Trie, error) {
|
||||
store: db.accountsCache,
|
||||
accountsCache: db.accountsCache,
|
||||
storageCache: db.storageCache,
|
||||
storeCache: db.storeCache,
|
||||
ethTrieDB: db.ethTrieDB,
|
||||
empty: isRootEmpty(root),
|
||||
root: rootHashFromVersion(db.stateStore.LastCommitID().Version),
|
||||
@ -154,10 +163,11 @@ func (db *Database) OpenStorageTrie(addrHash, root ethcmn.Hash) (ethstate.Trie,
|
||||
// a contract storage trie does not need an accountCache, storageCache or
|
||||
// an Ethereum trie because it will not be used upon commitment.
|
||||
return &Trie{
|
||||
store: db.storageCache,
|
||||
prefix: addrHash.Bytes(),
|
||||
empty: isRootEmpty(root),
|
||||
root: rootHashFromVersion(db.stateStore.LastCommitID().Version),
|
||||
store: db.storageCache,
|
||||
storeCache: db.storeCache,
|
||||
prefix: addrHash.Bytes(),
|
||||
empty: isRootEmpty(root),
|
||||
root: rootHashFromVersion(db.stateStore.LastCommitID().Version),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,8 @@ import (
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
ethdb "github.com/ethereum/go-ethereum/ethdb"
|
||||
ethtrie "github.com/ethereum/go-ethereum/trie"
|
||||
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -25,6 +27,8 @@ type Trie struct {
|
||||
// ordering.
|
||||
storageCache store.CacheKVStore
|
||||
|
||||
storeCache *lru.Cache
|
||||
|
||||
// Store is an IAVL KV store that is part of a larger store except it used
|
||||
// for a specific prefix. It will either be an accountsCache or a
|
||||
// storageCache.
|
||||
@ -64,8 +68,13 @@ func (t *Trie) TryGet(key []byte) ([]byte, error) {
|
||||
if t.IsStorageTrie() {
|
||||
key = t.prefixKey(key)
|
||||
}
|
||||
|
||||
return t.store.Get(key), nil
|
||||
keyStr := string(key)
|
||||
if cached, ok := t.storeCache.Get(keyStr); ok {
|
||||
return cached.([]byte), nil
|
||||
}
|
||||
value := t.store.Get(key)
|
||||
t.storeCache.Add(keyStr, value)
|
||||
return value, nil
|
||||
}
|
||||
|
||||
// TryUpdate implements the Ethereum state.Trie interface. It associates a
|
||||
@ -83,6 +92,7 @@ func (t *Trie) TryUpdate(key, value []byte) error {
|
||||
}
|
||||
|
||||
t.store.Set(key, value)
|
||||
t.storeCache.Add(string(key), value)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -98,6 +108,7 @@ func (t *Trie) TryDelete(key []byte) error {
|
||||
}
|
||||
|
||||
t.store.Delete(key)
|
||||
t.storeCache.Remove(string(key))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ var (
|
||||
cpuprofile = flag.String("cpu-profile", "", "write cpu profile `file`")
|
||||
blockchain = flag.String("blockchain", "data/blockchain", "file containing blocks to load")
|
||||
datadir = flag.String("datadir", path.Join(os.Getenv("HOME"), ".ethermint"), "directory for ethermint data")
|
||||
cachesize = flag.Int("cachesize", 1024*1024, "number of key-value pairs for the state stored in memory")
|
||||
)
|
||||
|
||||
func main() {
|
||||
@ -51,7 +52,7 @@ func main() {
|
||||
stateDB := dbm.NewDB("state", dbm.LevelDBBackend, *datadir)
|
||||
codeDB := dbm.NewDB("code", dbm.LevelDBBackend, *datadir)
|
||||
|
||||
ethermintDB, err := state.NewDatabase(stateDB, codeDB)
|
||||
ethermintDB, err := state.NewDatabase(stateDB, codeDB, *cachesize)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to initialize geth Database: %v", err))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user