core/state/snapshot: replace bigcache with fastcache

pull/20152/head
Martin Holst Swende 5 years ago committed by Péter Szilágyi
parent d754091a87
commit f300c0df01
No known key found for this signature in database
GPG Key ID: E9AE538CEDF8293D
  1. 14
      core/state/snapshot/disklayer.go
  2. 10
      core/state/snapshot/generate.go
  3. 22
      core/state/snapshot/snapshot.go
  4. 18
      core/state/snapshot/snapshot_test.go

@ -19,7 +19,7 @@ package snapshot
import ( import (
"sync" "sync"
"github.com/allegro/bigcache" "github.com/VictoriaMetrics/fastcache"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
@ -30,7 +30,7 @@ import (
type diskLayer struct { type diskLayer struct {
journal string // Path of the snapshot journal to use on shutdown journal string // Path of the snapshot journal to use on shutdown
db ethdb.KeyValueStore // Key-value store containing the base snapshot db ethdb.KeyValueStore // Key-value store containing the base snapshot
cache *bigcache.BigCache // Cache to avoid hitting the disk for direct access cache *fastcache.Cache // Cache to avoid hitting the disk for direct access
root common.Hash // Root hash of the base snapshot root common.Hash // Root hash of the base snapshot
stale bool // Signals that the layer became stale (state progressed) stale bool // Signals that the layer became stale (state progressed)
@ -80,17 +80,15 @@ func (dl *diskLayer) AccountRLP(hash common.Hash) ([]byte, error) {
if dl.stale { if dl.stale {
return nil, ErrSnapshotStale return nil, ErrSnapshotStale
} }
key := string(hash[:])
// Try to retrieve the account from the memory cache // Try to retrieve the account from the memory cache
if blob, err := dl.cache.Get(key); err == nil { if blob := dl.cache.Get(nil, hash[:]); blob != nil {
snapshotCleanHitMeter.Mark(1) snapshotCleanHitMeter.Mark(1)
snapshotCleanReadMeter.Mark(int64(len(blob))) snapshotCleanReadMeter.Mark(int64(len(blob)))
return blob, nil return blob, nil
} }
// Cache doesn't contain account, pull from disk and cache for later // Cache doesn't contain account, pull from disk and cache for later
blob := rawdb.ReadAccountSnapshot(dl.db, hash) blob := rawdb.ReadAccountSnapshot(dl.db, hash)
dl.cache.Set(key, blob) dl.cache.Set(hash[:], blob)
snapshotCleanMissMeter.Mark(1) snapshotCleanMissMeter.Mark(1)
snapshotCleanWriteMeter.Mark(int64(len(blob))) snapshotCleanWriteMeter.Mark(int64(len(blob)))
@ -109,10 +107,10 @@ func (dl *diskLayer) Storage(accountHash, storageHash common.Hash) ([]byte, erro
if dl.stale { if dl.stale {
return nil, ErrSnapshotStale return nil, ErrSnapshotStale
} }
key := string(append(accountHash[:], storageHash[:]...)) key := append(accountHash[:], storageHash[:]...)
// Try to retrieve the storage slot from the memory cache // Try to retrieve the storage slot from the memory cache
if blob, err := dl.cache.Get(key); err == nil { if blob := dl.cache.Get(nil, key); blob != nil {
snapshotCleanHitMeter.Mark(1) snapshotCleanHitMeter.Mark(1)
snapshotCleanReadMeter.Mark(int64(len(blob))) snapshotCleanReadMeter.Mark(int64(len(blob)))
return blob, nil return blob, nil

@ -22,7 +22,7 @@ import (
"math/big" "math/big"
"time" "time"
"github.com/allegro/bigcache" "github.com/VictoriaMetrics/fastcache"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
@ -196,13 +196,7 @@ func generateSnapshot(db ethdb.KeyValueStore, journal string, root common.Hash)
return nil, err return nil, err
} }
// New snapshot generated, construct a brand new base layer // New snapshot generated, construct a brand new base layer
cache, _ := bigcache.NewBigCache(bigcache.Config{ // TODO(karalabe): dedup cache := fastcache.New(512 * 1024 * 1024)
Shards: 1024,
LifeWindow: time.Hour,
MaxEntriesInWindow: 512 * 1024,
MaxEntrySize: 512,
HardMaxCacheSize: 512,
})
return &diskLayer{ return &diskLayer{
journal: journal, journal: journal,
db: db, db: db,

@ -22,9 +22,8 @@ import (
"fmt" "fmt"
"os" "os"
"sync" "sync"
"time"
"github.com/allegro/bigcache" "github.com/VictoriaMetrics/fastcache"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
@ -323,7 +322,7 @@ func diffToDisk(bottom *diffLayer) *diskLayer {
if len(data) > 0 { if len(data) > 0 {
// Account was updated, push to disk // Account was updated, push to disk
rawdb.WriteAccountSnapshot(batch, hash, data) rawdb.WriteAccountSnapshot(batch, hash, data)
base.cache.Set(string(hash[:]), data) base.cache.Set(hash[:], data)
if batch.ValueSize() > ethdb.IdealBatchSize { if batch.ValueSize() > ethdb.IdealBatchSize {
if err := batch.Write(); err != nil { if err := batch.Write(); err != nil {
@ -334,13 +333,13 @@ func diffToDisk(bottom *diffLayer) *diskLayer {
} else { } else {
// Account was deleted, remove all storage slots too // Account was deleted, remove all storage slots too
rawdb.DeleteAccountSnapshot(batch, hash) rawdb.DeleteAccountSnapshot(batch, hash)
base.cache.Set(string(hash[:]), nil) base.cache.Set(hash[:], nil)
it := rawdb.IterateStorageSnapshots(base.db, hash) it := rawdb.IterateStorageSnapshots(base.db, hash)
for it.Next() { for it.Next() {
if key := it.Key(); len(key) == 65 { // TODO(karalabe): Yuck, we should move this into the iterator if key := it.Key(); len(key) == 65 { // TODO(karalabe): Yuck, we should move this into the iterator
batch.Delete(key) batch.Delete(key)
base.cache.Delete(string(key[1:])) base.cache.Del(key[1:])
} }
} }
it.Release() it.Release()
@ -351,10 +350,10 @@ func diffToDisk(bottom *diffLayer) *diskLayer {
for storageHash, data := range storage { for storageHash, data := range storage {
if len(data) > 0 { if len(data) > 0 {
rawdb.WriteStorageSnapshot(batch, accountHash, storageHash, data) rawdb.WriteStorageSnapshot(batch, accountHash, storageHash, data)
base.cache.Set(string(append(accountHash[:], storageHash[:]...)), data) base.cache.Set(append(accountHash[:], storageHash[:]...), data)
} else { } else {
rawdb.DeleteStorageSnapshot(batch, accountHash, storageHash) rawdb.DeleteStorageSnapshot(batch, accountHash, storageHash)
base.cache.Set(string(append(accountHash[:], storageHash[:]...)), nil) base.cache.Set(append(accountHash[:], storageHash[:]...), nil)
} }
} }
if batch.ValueSize() > ethdb.IdealBatchSize { if batch.ValueSize() > ethdb.IdealBatchSize {
@ -401,17 +400,10 @@ func loadSnapshot(db ethdb.KeyValueStore, journal string, root common.Hash) (sna
if baseRoot == (common.Hash{}) { if baseRoot == (common.Hash{}) {
return nil, errors.New("missing or corrupted snapshot") return nil, errors.New("missing or corrupted snapshot")
} }
cache, _ := bigcache.NewBigCache(bigcache.Config{ // TODO(karalabe): dedup
Shards: 1024,
LifeWindow: time.Hour,
MaxEntriesInWindow: 512 * 1024,
MaxEntrySize: 512,
HardMaxCacheSize: 512,
})
base := &diskLayer{ base := &diskLayer{
journal: journal, journal: journal,
db: db, db: db,
cache: cache, cache: fastcache.New(512 * 1024 * 1024),
root: baseRoot, root: baseRoot,
} }
// Load all the snapshot diffs from the journal, failing if their chain is broken // Load all the snapshot diffs from the journal, failing if their chain is broken

@ -19,9 +19,8 @@ package snapshot
import ( import (
"fmt" "fmt"
"testing" "testing"
"time"
"github.com/allegro/bigcache" "github.com/VictoriaMetrics/fastcache"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
) )
@ -31,11 +30,10 @@ import (
// to check internal corner case around the bottom-most memory accumulator. // to check internal corner case around the bottom-most memory accumulator.
func TestDiskLayerExternalInvalidationFullFlatten(t *testing.T) { func TestDiskLayerExternalInvalidationFullFlatten(t *testing.T) {
// Create an empty base layer and a snapshot tree out of it // Create an empty base layer and a snapshot tree out of it
cache, _ := bigcache.NewBigCache(bigcache.DefaultConfig(time.Minute))
base := &diskLayer{ base := &diskLayer{
db: rawdb.NewMemoryDatabase(), db: rawdb.NewMemoryDatabase(),
root: common.HexToHash("0x01"), root: common.HexToHash("0x01"),
cache: cache, cache: fastcache.New(1024 * 500),
} }
snaps := &Tree{ snaps := &Tree{
layers: map[common.Hash]snapshot{ layers: map[common.Hash]snapshot{
@ -77,11 +75,10 @@ func TestDiskLayerExternalInvalidationFullFlatten(t *testing.T) {
// layer to check the usual mode of operation where the accumulator is retained. // layer to check the usual mode of operation where the accumulator is retained.
func TestDiskLayerExternalInvalidationPartialFlatten(t *testing.T) { func TestDiskLayerExternalInvalidationPartialFlatten(t *testing.T) {
// Create an empty base layer and a snapshot tree out of it // Create an empty base layer and a snapshot tree out of it
cache, _ := bigcache.NewBigCache(bigcache.DefaultConfig(time.Minute))
base := &diskLayer{ base := &diskLayer{
db: rawdb.NewMemoryDatabase(), db: rawdb.NewMemoryDatabase(),
root: common.HexToHash("0x01"), root: common.HexToHash("0x01"),
cache: cache, cache: fastcache.New(1024 * 500),
} }
snaps := &Tree{ snaps := &Tree{
layers: map[common.Hash]snapshot{ layers: map[common.Hash]snapshot{
@ -126,11 +123,10 @@ func TestDiskLayerExternalInvalidationPartialFlatten(t *testing.T) {
// to check internal corner case around the bottom-most memory accumulator. // to check internal corner case around the bottom-most memory accumulator.
func TestDiffLayerExternalInvalidationFullFlatten(t *testing.T) { func TestDiffLayerExternalInvalidationFullFlatten(t *testing.T) {
// Create an empty base layer and a snapshot tree out of it // Create an empty base layer and a snapshot tree out of it
cache, _ := bigcache.NewBigCache(bigcache.DefaultConfig(time.Minute))
base := &diskLayer{ base := &diskLayer{
db: rawdb.NewMemoryDatabase(), db: rawdb.NewMemoryDatabase(),
root: common.HexToHash("0x01"), root: common.HexToHash("0x01"),
cache: cache, cache: fastcache.New(1024 * 500),
} }
snaps := &Tree{ snaps := &Tree{
layers: map[common.Hash]snapshot{ layers: map[common.Hash]snapshot{
@ -175,11 +171,10 @@ func TestDiffLayerExternalInvalidationFullFlatten(t *testing.T) {
// layer to check the usual mode of operation where the accumulator is retained. // layer to check the usual mode of operation where the accumulator is retained.
func TestDiffLayerExternalInvalidationPartialFlatten(t *testing.T) { func TestDiffLayerExternalInvalidationPartialFlatten(t *testing.T) {
// Create an empty base layer and a snapshot tree out of it // Create an empty base layer and a snapshot tree out of it
cache, _ := bigcache.NewBigCache(bigcache.DefaultConfig(time.Minute))
base := &diskLayer{ base := &diskLayer{
db: rawdb.NewMemoryDatabase(), db: rawdb.NewMemoryDatabase(),
root: common.HexToHash("0x01"), root: common.HexToHash("0x01"),
cache: cache, cache: fastcache.New(1024 * 500),
} }
snaps := &Tree{ snaps := &Tree{
layers: map[common.Hash]snapshot{ layers: map[common.Hash]snapshot{
@ -240,11 +235,10 @@ func TestPostCapBasicDataAccess(t *testing.T) {
} }
} }
// Create a starting base layer and a snapshot tree out of it // Create a starting base layer and a snapshot tree out of it
cache, _ := bigcache.NewBigCache(bigcache.DefaultConfig(time.Minute))
base := &diskLayer{ base := &diskLayer{
db: rawdb.NewMemoryDatabase(), db: rawdb.NewMemoryDatabase(),
root: common.HexToHash("0x01"), root: common.HexToHash("0x01"),
cache: cache, cache: fastcache.New(1024 * 500),
} }
snaps := &Tree{ snaps := &Tree{
layers: map[common.Hash]snapshot{ layers: map[common.Hash]snapshot{

Loading…
Cancel
Save