core: cache UnspentCoins in cachedDao

1.5M block import time (VerifyBlocks disabled) on AMD Ryzen 5 1600/16GB/HDD,
before:
real    159m16.551s
user    69m58.279s
sys     7m34.334s

after:
real    139m41.836s
user    67m12.477s
sys     6m19.420s

12% which is even a bit more than could be expected from inputs analysis (that
has around 10% cache hits for a block-wide cache), worth doing.
This commit is contained in:
Roman Khimov 2020-03-11 12:13:02 +03:00
parent 23464401bc
commit 8c902a7223

View file

@ -13,13 +13,15 @@ type cachedDao struct {
dao dao
accounts map[util.Uint160]*state.Account accounts map[util.Uint160]*state.Account
contracts map[util.Uint160]*state.Contract contracts map[util.Uint160]*state.Contract
unspents map[util.Uint256]*state.UnspentCoin
} }
// newCachedDao returns new cachedDao wrapping around given backing store. // newCachedDao returns new cachedDao wrapping around given backing store.
func newCachedDao(backend storage.Store) *cachedDao { func newCachedDao(backend storage.Store) *cachedDao {
accs := make(map[util.Uint160]*state.Account) accs := make(map[util.Uint160]*state.Account)
ctrs := make(map[util.Uint160]*state.Contract) ctrs := make(map[util.Uint160]*state.Contract)
return &cachedDao{*newDao(backend), accs, ctrs} unspents := make(map[util.Uint256]*state.UnspentCoin)
return &cachedDao{*newDao(backend), accs, ctrs, unspents}
} }
// GetAccountStateOrNew retrieves Account from cache or underlying Store // GetAccountStateOrNew retrieves Account from cache or underlying Store
@ -69,6 +71,20 @@ func (cd *cachedDao) DeleteContractState(hash util.Uint160) error {
return cd.dao.DeleteContractState(hash) return cd.dao.DeleteContractState(hash)
} }
// GetUnspentCoinState retrieves UnspentCoin from cache or underlying Store.
func (cd *cachedDao) GetUnspentCoinState(hash util.Uint256) (*state.UnspentCoin, error) {
if cd.unspents[hash] != nil {
return cd.unspents[hash], nil
}
return cd.dao.GetUnspentCoinState(hash)
}
// PutUnspentCoinState saves given UnspentCoin in the cache.
func (cd *cachedDao) PutUnspentCoinState(hash util.Uint256, ucs *state.UnspentCoin) error {
cd.unspents[hash] = ucs
return nil
}
// Persist flushes all the changes made into the (supposedly) persistent // Persist flushes all the changes made into the (supposedly) persistent
// underlying store. // underlying store.
func (cd *cachedDao) Persist() (int, error) { func (cd *cachedDao) Persist() (int, error) {
@ -78,5 +94,11 @@ func (cd *cachedDao) Persist() (int, error) {
return 0, err return 0, err
} }
} }
for hash := range cd.unspents {
err := cd.dao.PutUnspentCoinState(hash, cd.unspents[hash])
if err != nil {
return 0, err
}
}
return cd.dao.Persist() return cd.dao.Persist()
} }