mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 05:36:46 +00:00
no global cache
Signed-off-by: Delweng <delweng@gmail.com>
This commit is contained in:
parent
faca680a13
commit
2b64c5c938
7 changed files with 114 additions and 71 deletions
|
|
@ -60,6 +60,9 @@ const (
|
|||
var (
|
||||
// maxDiffLayers is the maximum diff layers allowed in the layer tree.
|
||||
maxDiffLayers = 128
|
||||
|
||||
// historyCacheSize is the maximum size of history cache.
|
||||
historyCacheSize = 4096
|
||||
)
|
||||
|
||||
// layer is the interface implemented by all state layers which includes some
|
||||
|
|
@ -225,6 +228,7 @@ type Database struct {
|
|||
freezer ethdb.ResettableAncientStore // Freezer for storing trie histories, nil possible in tests
|
||||
lock sync.RWMutex // Lock to prevent mutations from happening at the same time
|
||||
indexer *historyIndexer // History indexer
|
||||
cacher *historyCacher // History cacher
|
||||
}
|
||||
|
||||
// New attempts to load an already existing layer from a persistent key-value
|
||||
|
|
@ -242,6 +246,7 @@ func New(diskdb ethdb.Database, config *Config, isVerkle bool) *Database {
|
|||
config: config,
|
||||
diskdb: diskdb,
|
||||
hasher: merkleNodeHasher,
|
||||
cacher: newHistoryCacher(historyCacheSize),
|
||||
}
|
||||
// Establish a dedicated database namespace tailored for verkle-specific
|
||||
// data, ensuring the isolation of both verkle and merkle tree data. It's
|
||||
|
|
@ -276,7 +281,7 @@ func New(diskdb ethdb.Database, config *Config, isVerkle bool) *Database {
|
|||
}
|
||||
// TODO (rjl493456442) disable the background indexing in read-only mode
|
||||
if db.freezer != nil && db.config.EnableStateIndexing {
|
||||
db.indexer = newHistoryIndexer(db.diskdb, db.freezer, db.tree.bottom().stateID())
|
||||
db.indexer = newHistoryIndexer(db.diskdb, db.freezer, db.tree.bottom().stateID(), db.cacher)
|
||||
log.Info("Enabled state history indexing")
|
||||
}
|
||||
fields := config.fields()
|
||||
|
|
@ -531,7 +536,7 @@ func (db *Database) Enable(root common.Hash) error {
|
|||
// 2. Re-initialize the indexer so it starts indexing from the new state root.
|
||||
if db.indexer != nil && db.freezer != nil && db.config.EnableStateIndexing {
|
||||
db.indexer.close()
|
||||
db.indexer = newHistoryIndexer(db.diskdb, db.freezer, db.tree.bottom().stateID())
|
||||
db.indexer = newHistoryIndexer(db.diskdb, db.freezer, db.tree.bottom().stateID(), db.cacher)
|
||||
log.Info("Re-enabled state history indexing")
|
||||
}
|
||||
log.Info("Rebuilt trie database", "root", root)
|
||||
|
|
|
|||
|
|
@ -76,15 +76,16 @@ type indexReader struct {
|
|||
readers map[uint32]*blockReader
|
||||
state stateIdent
|
||||
timings *readTimings
|
||||
cacher *historyCacher
|
||||
}
|
||||
|
||||
// loadIndexData loads the index data associated with the specified state.
|
||||
func loadIndexData(db ethdb.KeyValueReader, state stateIdent, timings *readTimings, cacheRead bool) ([]*indexBlockDesc, error) {
|
||||
func loadIndexData(db ethdb.KeyValueReader, state stateIdent, timings *readTimings, cacheRead bool, cacher *historyCacher) ([]*indexBlockDesc, error) {
|
||||
start := time.Now()
|
||||
key := state.String()
|
||||
var blob []byte
|
||||
if cacheRead && historyIndexCache.Contains(key) {
|
||||
blob, _ = historyIndexCache.Get(key)
|
||||
if cacheRead && cacher != nil && cacher.index.Contains(key) {
|
||||
blob, _ = cacher.index.Get(key)
|
||||
} else {
|
||||
if state.account {
|
||||
blob = rawdb.ReadAccountHistoryIndex(db, state.addressHash)
|
||||
|
|
@ -98,19 +99,21 @@ func loadIndexData(db ethdb.KeyValueReader, state stateIdent, timings *readTimin
|
|||
if len(blob) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
historyIndexCache.Add(key, blob)
|
||||
if cacher != nil {
|
||||
cacher.index.Add(key, blob)
|
||||
}
|
||||
return parseIndex(blob)
|
||||
}
|
||||
|
||||
// newIndexReader constructs a index reader for the specified state. Reader with
|
||||
// empty data is allowed.
|
||||
func newIndexReader(db ethdb.KeyValueReader, state stateIdent) (*indexReader, error) {
|
||||
return newIndexReaderWithTimings(db, state, nil)
|
||||
func newIndexReader(db ethdb.KeyValueReader, state stateIdent, cacher *historyCacher) (*indexReader, error) {
|
||||
return newIndexReaderWithTimings(db, state, nil, cacher)
|
||||
}
|
||||
|
||||
// Helper to allow passing timings
|
||||
func newIndexReaderWithTimings(db ethdb.KeyValueReader, state stateIdent, timings *readTimings) (*indexReader, error) {
|
||||
descList, err := loadIndexData(db, state, timings, true)
|
||||
func newIndexReaderWithTimings(db ethdb.KeyValueReader, state stateIdent, timings *readTimings, cacher *historyCacher) (*indexReader, error) {
|
||||
descList, err := loadIndexData(db, state, timings, true, cacher)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -120,6 +123,7 @@ func newIndexReaderWithTimings(db ethdb.KeyValueReader, state stateIdent, timing
|
|||
db: db,
|
||||
state: state,
|
||||
timings: timings,
|
||||
cacher: cacher,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -134,7 +138,7 @@ func (r *indexReader) refresh() error {
|
|||
delete(r.readers, last.id)
|
||||
}
|
||||
}
|
||||
descList, err := loadIndexData(r.db, r.state, r.timings, false)
|
||||
descList, err := loadIndexData(r.db, r.state, r.timings, false, r.cacher)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -161,16 +165,17 @@ func (r *indexReader) readGreaterThan(id uint64) (uint64, error) {
|
|||
)
|
||||
start := time.Now()
|
||||
key := fmt.Sprintf("%s:%d", r.state.String(), desc.id)
|
||||
if val, ok := historyBlockCache.Get(key); ok {
|
||||
blob = val
|
||||
if r.cacher != nil && r.cacher.block.Contains(key) {
|
||||
blob, _ = r.cacher.block.Get(key)
|
||||
} else {
|
||||
if r.state.account {
|
||||
blob = rawdb.ReadAccountHistoryIndexBlock(r.db, r.state.addressHash, desc.id)
|
||||
} else {
|
||||
blob = rawdb.ReadStorageHistoryIndexBlock(r.db, r.state.addressHash, r.state.storageHash, desc.id)
|
||||
}
|
||||
if len(blob) > 0 {
|
||||
historyBlockCache.Add(key, blob)
|
||||
|
||||
if r.cacher != nil && len(blob) > 0 {
|
||||
r.cacher.block.Add(key, blob)
|
||||
}
|
||||
}
|
||||
if r.timings != nil {
|
||||
|
|
@ -200,10 +205,11 @@ type indexWriter struct {
|
|||
lastID uint64 // The ID of the latest tracked history
|
||||
state stateIdent
|
||||
db ethdb.KeyValueReader
|
||||
cacher *historyCacher
|
||||
}
|
||||
|
||||
// newIndexWriter constructs the index writer for the specified state.
|
||||
func newIndexWriter(db ethdb.KeyValueReader, state stateIdent) (*indexWriter, error) {
|
||||
func newIndexWriter(db ethdb.KeyValueReader, state stateIdent, cacher *historyCacher) (*indexWriter, error) {
|
||||
var blob []byte
|
||||
if state.account {
|
||||
blob = rawdb.ReadAccountHistoryIndex(db, state.addressHash)
|
||||
|
|
@ -218,6 +224,7 @@ func newIndexWriter(db ethdb.KeyValueReader, state stateIdent) (*indexWriter, er
|
|||
bw: bw,
|
||||
state: state,
|
||||
db: db,
|
||||
cacher: cacher,
|
||||
}, nil
|
||||
}
|
||||
descList, err := parseIndex(blob)
|
||||
|
|
@ -243,6 +250,7 @@ func newIndexWriter(db ethdb.KeyValueReader, state stateIdent) (*indexWriter, er
|
|||
bw: bw,
|
||||
state: state,
|
||||
db: db,
|
||||
cacher: cacher,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -301,8 +309,10 @@ func (w *indexWriter) finish(batch ethdb.Batch) {
|
|||
}
|
||||
for _, bw := range writers {
|
||||
buf := bw.finish()
|
||||
if key := fmt.Sprintf("%s:%d", w.state.String(), bw.desc.id); historyBlockCache.Contains(key) {
|
||||
historyBlockCache.Add(key, buf)
|
||||
if w.cacher != nil {
|
||||
if key := fmt.Sprintf("%s:%d", w.state.String(), bw.desc.id); w.cacher.block.Contains(key) {
|
||||
w.cacher.block.Add(key, buf)
|
||||
}
|
||||
}
|
||||
if w.state.account {
|
||||
rawdb.WriteAccountHistoryIndexBlock(batch, w.state.addressHash, bw.desc.id, buf)
|
||||
|
|
@ -316,8 +326,10 @@ func (w *indexWriter) finish(batch ethdb.Batch) {
|
|||
for _, desc := range descList {
|
||||
buf = append(buf, desc.encode()...)
|
||||
}
|
||||
if key := w.state.String(); historyIndexCache.Contains(key) {
|
||||
historyIndexCache.Add(key, buf)
|
||||
if w.cacher != nil {
|
||||
if key := w.state.String(); w.cacher.index.Contains(key) {
|
||||
w.cacher.index.Add(key, buf)
|
||||
}
|
||||
}
|
||||
if w.state.account {
|
||||
rawdb.WriteAccountHistoryIndex(batch, w.state.addressHash, buf)
|
||||
|
|
@ -334,10 +346,11 @@ type indexDeleter struct {
|
|||
lastID uint64 // The ID of the latest tracked history
|
||||
state stateIdent
|
||||
db ethdb.KeyValueReader
|
||||
cacher *historyCacher
|
||||
}
|
||||
|
||||
// newIndexDeleter constructs the index deleter for the specified state.
|
||||
func newIndexDeleter(db ethdb.KeyValueReader, state stateIdent) (*indexDeleter, error) {
|
||||
func newIndexDeleter(db ethdb.KeyValueReader, state stateIdent, cacher *historyCacher) (*indexDeleter, error) {
|
||||
var blob []byte
|
||||
if state.account {
|
||||
blob = rawdb.ReadAccountHistoryIndex(db, state.addressHash)
|
||||
|
|
@ -354,6 +367,7 @@ func newIndexDeleter(db ethdb.KeyValueReader, state stateIdent) (*indexDeleter,
|
|||
bw: bw,
|
||||
state: state,
|
||||
db: db,
|
||||
cacher: cacher,
|
||||
}, nil
|
||||
}
|
||||
descList, err := parseIndex(blob)
|
||||
|
|
@ -379,6 +393,7 @@ func newIndexDeleter(db ethdb.KeyValueReader, state stateIdent) (*indexDeleter,
|
|||
bw: bw,
|
||||
state: state,
|
||||
db: db,
|
||||
cacher: cacher,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -436,9 +451,10 @@ func (d *indexDeleter) pop(id uint64) error {
|
|||
// This function is safe to be called multiple times.
|
||||
func (d *indexDeleter) finish(batch ethdb.Batch) {
|
||||
for _, id := range d.dropped {
|
||||
key := fmt.Sprintf("%s:%d", d.state.String(), id)
|
||||
if historyBlockCache.Contains(key) {
|
||||
historyBlockCache.Remove(key)
|
||||
if d.cacher != nil {
|
||||
if key := fmt.Sprintf("%s:%d", d.state.String(), id); d.cacher.block.Contains(key) {
|
||||
d.cacher.block.Remove(key)
|
||||
}
|
||||
}
|
||||
if d.state.account {
|
||||
rawdb.DeleteAccountHistoryIndexBlock(batch, d.state.addressHash, id)
|
||||
|
|
@ -451,9 +467,10 @@ func (d *indexDeleter) finish(batch ethdb.Batch) {
|
|||
// Flush the content of last block writer, regardless it's dirty or not
|
||||
if !d.bw.empty() {
|
||||
buf := d.bw.finish()
|
||||
key := fmt.Sprintf("%s:%d", d.state.String(), d.bw.desc.id)
|
||||
if historyBlockCache.Contains(key) {
|
||||
historyBlockCache.Add(key, buf)
|
||||
if d.cacher != nil {
|
||||
if key := fmt.Sprintf("%s:%d", d.state.String(), d.bw.desc.id); d.cacher.block.Contains(key) {
|
||||
d.cacher.block.Add(key, buf)
|
||||
}
|
||||
}
|
||||
|
||||
if d.state.account {
|
||||
|
|
@ -464,8 +481,10 @@ func (d *indexDeleter) finish(batch ethdb.Batch) {
|
|||
}
|
||||
// Flush the index metadata into the supplied batch
|
||||
if d.empty() {
|
||||
if key := d.state.String(); historyIndexCache.Contains(key) {
|
||||
historyIndexCache.Remove(key)
|
||||
if d.cacher != nil {
|
||||
if key := d.state.String(); d.cacher.index.Contains(key) {
|
||||
d.cacher.index.Remove(key)
|
||||
}
|
||||
}
|
||||
if d.state.account {
|
||||
rawdb.DeleteAccountHistoryIndex(batch, d.state.addressHash)
|
||||
|
|
@ -477,8 +496,11 @@ func (d *indexDeleter) finish(batch ethdb.Batch) {
|
|||
for _, desc := range d.descList {
|
||||
buf = append(buf, desc.encode()...)
|
||||
}
|
||||
if key := d.state.String(); historyIndexCache.Contains(key) {
|
||||
historyIndexCache.Add(key, buf)
|
||||
|
||||
if d.cacher != nil {
|
||||
if key := d.state.String(); d.cacher.index.Contains(key) {
|
||||
d.cacher.index.Add(key, buf)
|
||||
}
|
||||
}
|
||||
|
||||
if d.state.account {
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ func TestIndexReaderBasic(t *testing.T) {
|
|||
1, 5, 10, 11, 20,
|
||||
}
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
bw, _ := newIndexWriter(db, newAccountIdent(common.Hash{0xa}))
|
||||
bw, _ := newIndexWriter(db, newAccountIdent(common.Hash{0xa}), nil)
|
||||
for i := 0; i < len(elements); i++ {
|
||||
bw.append(elements[i])
|
||||
}
|
||||
|
|
@ -41,7 +41,7 @@ func TestIndexReaderBasic(t *testing.T) {
|
|||
bw.finish(batch)
|
||||
batch.Write()
|
||||
|
||||
br, err := newIndexReader(db, newAccountIdent(common.Hash{0xa}))
|
||||
br, err := newIndexReader(db, newAccountIdent(common.Hash{0xa}), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to construct the index reader, %v", err)
|
||||
}
|
||||
|
|
@ -75,7 +75,7 @@ func TestIndexReaderLarge(t *testing.T) {
|
|||
slices.Sort(elements)
|
||||
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
bw, _ := newIndexWriter(db, newAccountIdent(common.Hash{0xa}))
|
||||
bw, _ := newIndexWriter(db, newAccountIdent(common.Hash{0xa}), nil)
|
||||
for i := 0; i < len(elements); i++ {
|
||||
bw.append(elements[i])
|
||||
}
|
||||
|
|
@ -83,7 +83,7 @@ func TestIndexReaderLarge(t *testing.T) {
|
|||
bw.finish(batch)
|
||||
batch.Write()
|
||||
|
||||
br, err := newIndexReader(db, newAccountIdent(common.Hash{0xa}))
|
||||
br, err := newIndexReader(db, newAccountIdent(common.Hash{0xa}), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to construct the index reader, %v", err)
|
||||
}
|
||||
|
|
@ -107,7 +107,7 @@ func TestIndexReaderLarge(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestEmptyIndexReader(t *testing.T) {
|
||||
br, err := newIndexReader(rawdb.NewMemoryDatabase(), newAccountIdent(common.Hash{0xa}))
|
||||
br, err := newIndexReader(rawdb.NewMemoryDatabase(), newAccountIdent(common.Hash{0xa}), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to construct the index reader, %v", err)
|
||||
}
|
||||
|
|
@ -122,7 +122,7 @@ func TestEmptyIndexReader(t *testing.T) {
|
|||
|
||||
func TestIndexWriterBasic(t *testing.T) {
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
iw, _ := newIndexWriter(db, newAccountIdent(common.Hash{0xa}))
|
||||
iw, _ := newIndexWriter(db, newAccountIdent(common.Hash{0xa}), nil)
|
||||
iw.append(2)
|
||||
if err := iw.append(1); err == nil {
|
||||
t.Fatal("out-of-order insertion is not expected")
|
||||
|
|
@ -134,7 +134,7 @@ func TestIndexWriterBasic(t *testing.T) {
|
|||
iw.finish(batch)
|
||||
batch.Write()
|
||||
|
||||
iw, err := newIndexWriter(db, newAccountIdent(common.Hash{0xa}))
|
||||
iw, err := newIndexWriter(db, newAccountIdent(common.Hash{0xa}), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to construct the block writer, %v", err)
|
||||
}
|
||||
|
|
@ -148,7 +148,7 @@ func TestIndexWriterBasic(t *testing.T) {
|
|||
|
||||
func TestIndexWriterDelete(t *testing.T) {
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
iw, _ := newIndexWriter(db, newAccountIdent(common.Hash{0xa}))
|
||||
iw, _ := newIndexWriter(db, newAccountIdent(common.Hash{0xa}), nil)
|
||||
for i := 0; i < indexBlockEntriesCap*4; i++ {
|
||||
iw.append(uint64(i + 1))
|
||||
}
|
||||
|
|
@ -157,7 +157,7 @@ func TestIndexWriterDelete(t *testing.T) {
|
|||
batch.Write()
|
||||
|
||||
// Delete unknown id, the request should be rejected
|
||||
id, _ := newIndexDeleter(db, newAccountIdent(common.Hash{0xa}))
|
||||
id, _ := newIndexDeleter(db, newAccountIdent(common.Hash{0xa}), nil)
|
||||
if err := id.pop(indexBlockEntriesCap * 5); err == nil {
|
||||
t.Fatal("Expect error to occur for unknown id")
|
||||
}
|
||||
|
|
@ -179,7 +179,7 @@ func TestIndexWriterDelete(t *testing.T) {
|
|||
func TestBatchIndexerWrite(t *testing.T) {
|
||||
var (
|
||||
db = rawdb.NewMemoryDatabase()
|
||||
batch = newBatchIndexer(db, false)
|
||||
batch = newBatchIndexer(db, nil, false)
|
||||
histories = makeHistories(10)
|
||||
)
|
||||
for i, h := range histories {
|
||||
|
|
@ -212,7 +212,7 @@ func TestBatchIndexerWrite(t *testing.T) {
|
|||
}
|
||||
}
|
||||
for addrHash, indexes := range accounts {
|
||||
ir, _ := newIndexReader(db, newAccountIdent(addrHash))
|
||||
ir, _ := newIndexReader(db, newAccountIdent(addrHash), nil)
|
||||
for i := 0; i < len(indexes)-1; i++ {
|
||||
n, err := ir.readGreaterThan(indexes[i])
|
||||
if err != nil {
|
||||
|
|
@ -232,7 +232,7 @@ func TestBatchIndexerWrite(t *testing.T) {
|
|||
}
|
||||
for addrHash, slots := range storages {
|
||||
for slotHash, indexes := range slots {
|
||||
ir, _ := newIndexReader(db, newStorageIdent(addrHash, slotHash))
|
||||
ir, _ := newIndexReader(db, newStorageIdent(addrHash, slotHash), nil)
|
||||
for i := 0; i < len(indexes)-1; i++ {
|
||||
n, err := ir.readGreaterThan(indexes[i])
|
||||
if err != nil {
|
||||
|
|
@ -256,7 +256,7 @@ func TestBatchIndexerWrite(t *testing.T) {
|
|||
func TestBatchIndexerDelete(t *testing.T) {
|
||||
var (
|
||||
db = rawdb.NewMemoryDatabase()
|
||||
bw = newBatchIndexer(db, false)
|
||||
bw = newBatchIndexer(db, nil, false)
|
||||
histories = makeHistories(10)
|
||||
)
|
||||
// Index histories
|
||||
|
|
@ -270,7 +270,7 @@ func TestBatchIndexerDelete(t *testing.T) {
|
|||
}
|
||||
|
||||
// Unindex histories
|
||||
bd := newBatchIndexer(db, true)
|
||||
bd := newBatchIndexer(db, nil, true)
|
||||
for i := len(histories) - 1; i >= 0; i-- {
|
||||
if err := bd.process(histories[i], uint64(i+1)); err != nil {
|
||||
t.Fatalf("Failed to process history, %v", err)
|
||||
|
|
|
|||
|
|
@ -79,15 +79,17 @@ type batchIndexer struct {
|
|||
delete bool // Index or unindex mode
|
||||
lastID uint64 // The ID of latest processed history
|
||||
db ethdb.KeyValueStore
|
||||
cacher *historyCacher
|
||||
}
|
||||
|
||||
// newBatchIndexer constructs the batch indexer with the supplied mode.
|
||||
func newBatchIndexer(db ethdb.KeyValueStore, delete bool) *batchIndexer {
|
||||
func newBatchIndexer(db ethdb.KeyValueStore, cacher *historyCacher, delete bool) *batchIndexer {
|
||||
return &batchIndexer{
|
||||
accounts: make(map[common.Hash][]uint64),
|
||||
storages: make(map[common.Hash]map[common.Hash][]uint64),
|
||||
delete: delete,
|
||||
db: db,
|
||||
cacher: cacher,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -139,7 +141,7 @@ func (b *batchIndexer) finish(force bool) error {
|
|||
for addrHash, idList := range b.accounts {
|
||||
eg.Go(func() error {
|
||||
if !b.delete {
|
||||
iw, err := newIndexWriter(b.db, newAccountIdent(addrHash))
|
||||
iw, err := newIndexWriter(b.db, newAccountIdent(addrHash), b.cacher)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -152,7 +154,7 @@ func (b *batchIndexer) finish(force bool) error {
|
|||
iw.finish(batch)
|
||||
batchMu.Unlock()
|
||||
} else {
|
||||
id, err := newIndexDeleter(b.db, newAccountIdent(addrHash))
|
||||
id, err := newIndexDeleter(b.db, newAccountIdent(addrHash), b.cacher)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -173,7 +175,7 @@ func (b *batchIndexer) finish(force bool) error {
|
|||
for storageHash, idList := range slots {
|
||||
eg.Go(func() error {
|
||||
if !b.delete {
|
||||
iw, err := newIndexWriter(b.db, newStorageIdent(addrHash, storageHash))
|
||||
iw, err := newIndexWriter(b.db, newStorageIdent(addrHash, storageHash), b.cacher)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -186,7 +188,7 @@ func (b *batchIndexer) finish(force bool) error {
|
|||
iw.finish(batch)
|
||||
batchMu.Unlock()
|
||||
} else {
|
||||
id, err := newIndexDeleter(b.db, newStorageIdent(addrHash, storageHash))
|
||||
id, err := newIndexDeleter(b.db, newStorageIdent(addrHash, storageHash), b.cacher)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -227,7 +229,7 @@ func (b *batchIndexer) finish(force bool) error {
|
|||
}
|
||||
|
||||
// indexSingle processes the state history with the specified ID for indexing.
|
||||
func indexSingle(historyID uint64, db ethdb.KeyValueStore, freezer ethdb.AncientReader) error {
|
||||
func indexSingle(historyID uint64, db ethdb.KeyValueStore, freezer ethdb.AncientReader, cacher *historyCacher) error {
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
indexHistoryTimer.UpdateSince(start)
|
||||
|
|
@ -245,7 +247,7 @@ func indexSingle(historyID uint64, db ethdb.KeyValueStore, freezer ethdb.Ancient
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b := newBatchIndexer(db, false)
|
||||
b := newBatchIndexer(db, cacher, false)
|
||||
if err := b.process(h, historyID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -257,7 +259,7 @@ func indexSingle(historyID uint64, db ethdb.KeyValueStore, freezer ethdb.Ancient
|
|||
}
|
||||
|
||||
// unindexSingle processes the state history with the specified ID for unindexing.
|
||||
func unindexSingle(historyID uint64, db ethdb.KeyValueStore, freezer ethdb.AncientReader) error {
|
||||
func unindexSingle(historyID uint64, db ethdb.KeyValueStore, freezer ethdb.AncientReader, cacher *historyCacher) error {
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
unindexHistoryTimer.UpdateSince(start)
|
||||
|
|
@ -275,7 +277,7 @@ func unindexSingle(historyID uint64, db ethdb.KeyValueStore, freezer ethdb.Ancie
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b := newBatchIndexer(db, true)
|
||||
b := newBatchIndexer(db, cacher, true)
|
||||
if err := b.process(h, historyID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -302,6 +304,7 @@ type interruptSignal struct {
|
|||
type indexIniter struct {
|
||||
disk ethdb.KeyValueStore
|
||||
freezer ethdb.AncientStore
|
||||
cacher *historyCacher
|
||||
interrupt chan *interruptSignal
|
||||
done chan struct{}
|
||||
closed chan struct{}
|
||||
|
|
@ -416,7 +419,7 @@ func (i *indexIniter) run(lastID uint64) {
|
|||
// been fully indexed, unindex it here and shut down the initializer.
|
||||
if checkDone() {
|
||||
log.Info("Truncate the extra history", "id", lastID)
|
||||
if err := unindexSingle(lastID, i.disk, i.freezer); err != nil {
|
||||
if err := unindexSingle(lastID, i.disk, i.freezer, i.cacher); err != nil {
|
||||
signal.result <- err
|
||||
return
|
||||
}
|
||||
|
|
@ -517,7 +520,7 @@ func (i *indexIniter) index(done chan struct{}, interrupt *atomic.Int32, lastID
|
|||
current = beginID
|
||||
start = time.Now()
|
||||
logged = time.Now()
|
||||
batch = newBatchIndexer(i.disk, false)
|
||||
batch = newBatchIndexer(i.disk, i.cacher, false)
|
||||
)
|
||||
for current <= lastID {
|
||||
count := lastID - current + 1
|
||||
|
|
@ -585,6 +588,7 @@ type historyIndexer struct {
|
|||
initer *indexIniter
|
||||
disk ethdb.KeyValueStore
|
||||
freezer ethdb.AncientStore
|
||||
cacher *historyCacher
|
||||
}
|
||||
|
||||
// checkVersion checks whether the index data in the database matches the version.
|
||||
|
|
@ -611,12 +615,13 @@ func checkVersion(disk ethdb.KeyValueStore) {
|
|||
|
||||
// newHistoryIndexer constructs the history indexer and launches the background
|
||||
// initer to complete the indexing of any remaining state histories.
|
||||
func newHistoryIndexer(disk ethdb.KeyValueStore, freezer ethdb.AncientStore, lastHistoryID uint64) *historyIndexer {
|
||||
func newHistoryIndexer(disk ethdb.KeyValueStore, freezer ethdb.AncientStore, lastHistoryID uint64, cacher *historyCacher) *historyIndexer {
|
||||
checkVersion(disk)
|
||||
return &historyIndexer{
|
||||
initer: newIndexIniter(disk, freezer, lastHistoryID),
|
||||
disk: disk,
|
||||
freezer: freezer,
|
||||
cacher: cacher,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -642,7 +647,7 @@ func (i *historyIndexer) extend(historyID uint64) error {
|
|||
case <-i.initer.closed:
|
||||
return errors.New("indexer is closed")
|
||||
case <-i.initer.done:
|
||||
return indexSingle(historyID, i.disk, i.freezer)
|
||||
return indexSingle(historyID, i.disk, i.freezer, i.cacher)
|
||||
case i.initer.interrupt <- signal:
|
||||
return <-signal.result
|
||||
}
|
||||
|
|
@ -659,7 +664,7 @@ func (i *historyIndexer) shorten(historyID uint64) error {
|
|||
case <-i.initer.closed:
|
||||
return errors.New("indexer is closed")
|
||||
case <-i.initer.done:
|
||||
return unindexSingle(historyID, i.disk, i.freezer)
|
||||
return unindexSingle(historyID, i.disk, i.freezer, i.cacher)
|
||||
case i.initer.interrupt <- signal:
|
||||
return <-signal.result
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,11 +32,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/log"
|
||||
)
|
||||
|
||||
var (
|
||||
historyIndexCache = lru.NewCache[string, []byte](10000)
|
||||
historyBlockCache = lru.NewCache[string, []byte](10000)
|
||||
)
|
||||
|
||||
// stateIdent represents the identifier of a state element, which can be
|
||||
// either an account or a storage slot.
|
||||
type stateIdent struct {
|
||||
|
|
@ -131,8 +126,8 @@ type indexReaderWithLimitTag struct {
|
|||
|
||||
// newIndexReaderWithLimitTag constructs a index reader with indexing position.
|
||||
// Add timings parameter to pass through
|
||||
func newIndexReaderWithLimitTag(db ethdb.KeyValueReader, state stateIdent, limit uint64, timings *readTimings) (*indexReaderWithLimitTag, error) {
|
||||
r, err := newIndexReaderWithTimings(db, state, timings)
|
||||
func newIndexReaderWithLimitTag(db ethdb.KeyValueReader, state stateIdent, limit uint64, timings *readTimings, cacher *historyCacher) (*indexReaderWithLimitTag, error) {
|
||||
r, err := newIndexReaderWithTimings(db, state, timings, cacher)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -190,19 +185,35 @@ func (r *indexReaderWithLimitTag) readGreaterThan(id uint64, lastID uint64) (uin
|
|||
return r.reader.readGreaterThan(id)
|
||||
}
|
||||
|
||||
// historyCacher is responsible for caching history objects in memory to speed up access.
|
||||
type historyCacher struct {
|
||||
index *lru.Cache[string, []byte]
|
||||
block *lru.Cache[string, []byte]
|
||||
}
|
||||
|
||||
// newHistoryCacher creates a new historyCacher instance.
|
||||
func newHistoryCacher(size int) *historyCacher {
|
||||
return &historyCacher{
|
||||
index: lru.NewCache[string, []byte](size),
|
||||
block: lru.NewCache[string, []byte](size),
|
||||
}
|
||||
}
|
||||
|
||||
// historyReader is the structure to access historic state data.
|
||||
type historyReader struct {
|
||||
disk ethdb.KeyValueReader
|
||||
freezer ethdb.AncientReader
|
||||
readers map[string]*indexReaderWithLimitTag
|
||||
cacher *historyCacher
|
||||
}
|
||||
|
||||
// newHistoryReader constructs the history reader with the supplied db.
|
||||
func newHistoryReader(disk ethdb.KeyValueReader, freezer ethdb.AncientReader) *historyReader {
|
||||
// newHistoryReader constructs the history reader with the supplied db and cacher.
|
||||
func newHistoryReader(disk ethdb.KeyValueReader, freezer ethdb.AncientReader, cacher *historyCacher) *historyReader {
|
||||
return &historyReader{
|
||||
disk: disk,
|
||||
freezer: freezer,
|
||||
readers: make(map[string]*indexReaderWithLimitTag),
|
||||
cacher: cacher,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -386,7 +397,7 @@ func (r *historyReader) read(state stateIdentQuery, stateID uint64, lastID uint6
|
|||
// state retrieval
|
||||
ir, ok := r.readers[state.String()]
|
||||
if !ok {
|
||||
ir, err = newIndexReaderWithLimitTag(r.disk, state.stateIdent, metadata.Last, timings)
|
||||
ir, err = newIndexReaderWithLimitTag(r.disk, state.stateIdent, metadata.Last, timings, r.cacher)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ func testHistoryReader(t *testing.T, historyLimit uint64) {
|
|||
var (
|
||||
roots = env.roots
|
||||
dRoot = env.db.tree.bottom().rootHash()
|
||||
hr = newHistoryReader(env.db.diskdb, env.db.freezer)
|
||||
hr = newHistoryReader(env.db.diskdb, env.db.freezer, env.db.cacher)
|
||||
)
|
||||
for _, root := range roots {
|
||||
if root == dRoot {
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ func (db *Database) HistoricReader(root common.Hash) (*HistoricalStateReader, er
|
|||
return &HistoricalStateReader{
|
||||
id: *id,
|
||||
db: db,
|
||||
reader: newHistoryReader(db.diskdb, db.freezer),
|
||||
reader: newHistoryReader(db.diskdb, db.freezer, db.cacher),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue