core, ethdb, trie: mode dirty data to clean cache on flush (#19307)
This PR is a more advanced form of the dirty-to-clean cacher (#18995), where we reuse previous database write batches as datasets to uncache, saving a dirty-trie-iteration and a dirty-trie-rlp-reencoding per block.
This commit is contained in:
committed by
Felix Lange
parent
df717abc99
commit
59e1953246
@ -24,7 +24,6 @@ const IdealBatchSize = 100 * 1024
|
||||
// when Write is called. A batch cannot be used concurrently.
|
||||
type Batch interface {
|
||||
Writer
|
||||
Deleter
|
||||
|
||||
// ValueSize retrieves the amount of data queued up for writing.
|
||||
ValueSize() int
|
||||
@ -32,8 +31,11 @@ type Batch interface {
|
||||
// Write flushes any accumulated data to disk.
|
||||
Write() error
|
||||
|
||||
// Reset resets the batch for reuse
|
||||
// Reset resets the batch for reuse.
|
||||
Reset()
|
||||
|
||||
// Replay replays the batch contents.
|
||||
Replay(w Writer) error
|
||||
}
|
||||
|
||||
// Batcher wraps the NewBatch method of a backing data store.
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Package database defines the interfaces for an Ethereum data store.
|
||||
// Package ethdb defines the interfaces for an Ethereum data store.
|
||||
package ethdb
|
||||
|
||||
import "io"
|
||||
@ -32,10 +32,7 @@ type Reader interface {
|
||||
type Writer interface {
|
||||
// Put inserts the given value into the key-value data store.
|
||||
Put(key []byte, value []byte) error
|
||||
}
|
||||
|
||||
// Deleter wraps the Delete method of a backing data store.
|
||||
type Deleter interface {
|
||||
// Delete removes the key from the key-value data store.
|
||||
Delete(key []byte) error
|
||||
}
|
||||
@ -63,7 +60,6 @@ type Compacter interface {
|
||||
type KeyValueStore interface {
|
||||
Reader
|
||||
Writer
|
||||
Deleter
|
||||
Batcher
|
||||
Iteratee
|
||||
Stater
|
||||
@ -76,7 +72,6 @@ type KeyValueStore interface {
|
||||
type Database interface {
|
||||
Reader
|
||||
Writer
|
||||
Deleter
|
||||
Batcher
|
||||
Iteratee
|
||||
Stater
|
||||
|
@ -416,3 +416,32 @@ func (b *batch) Reset() {
|
||||
b.b.Reset()
|
||||
b.size = 0
|
||||
}
|
||||
|
||||
// Replay replays the batch contents.
|
||||
func (b *batch) Replay(w ethdb.Writer) error {
|
||||
return b.b.Replay(&replayer{writer: w})
|
||||
}
|
||||
|
||||
// replayer is a small wrapper to implement the correct replay methods.
|
||||
type replayer struct {
|
||||
writer ethdb.Writer
|
||||
failure error
|
||||
}
|
||||
|
||||
// Put inserts the given value into the key-value data store.
|
||||
func (r *replayer) Put(key, value []byte) {
|
||||
// If the replay already failed, stop executing ops
|
||||
if r.failure != nil {
|
||||
return
|
||||
}
|
||||
r.failure = r.writer.Put(key, value)
|
||||
}
|
||||
|
||||
// Delete removes the key from the key-value data store.
|
||||
func (r *replayer) Delete(key []byte) {
|
||||
// If the replay already failed, stop executing ops
|
||||
if r.failure != nil {
|
||||
return
|
||||
}
|
||||
r.failure = r.writer.Delete(key)
|
||||
}
|
||||
|
@ -240,6 +240,22 @@ func (b *batch) Reset() {
|
||||
b.size = 0
|
||||
}
|
||||
|
||||
// Replay replays the batch contents.
|
||||
func (b *batch) Replay(w ethdb.Writer) error {
|
||||
for _, keyvalue := range b.writes {
|
||||
if keyvalue.delete {
|
||||
if err := w.Delete(keyvalue.key); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err := w.Put(keyvalue.key, keyvalue.value); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// iterator can walk over the (potentially partial) keyspace of a memory key
|
||||
// value store. Internally it is a deep copy of the entire iterated state,
|
||||
// sorted by keys.
|
||||
|
Reference in New Issue
Block a user