reuse VMState and AccountsCache for better performance

This commit is contained in:
jangko 2020-06-15 13:28:08 +07:00
parent 49460b6b1e
commit bd7e1fe2e5
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
4 changed files with 46 additions and 6 deletions

View File

@ -33,6 +33,7 @@ type
trie: SecureHexaryTrie
savePoint: SavePoint
witnessCache: Table[EthAddress, WitnessData]
isDirty: bool
ReadOnlyStateDB* = distinct AccountsCache
@ -46,7 +47,17 @@ type
cache: Table[EthAddress, RefAccount]
state: TransactionState
const emptyAcc = newAccount()
const
emptyAcc = newAccount()
resetFlags = {
IsDirty,
IsNew,
IsTouched,
IsClone,
CodeChanged,
StorageChanged
}
proc beginSavepoint*(ac: var AccountsCache): SavePoint {.gcsafe.}
@ -66,7 +77,7 @@ proc rootHash*(ac: AccountsCache): KeccakHash =
# make sure all savepoint already committed
doAssert(ac.savePoint.parentSavePoint.isNil)
# make sure all cache already committed
doAssert(ac.savePoint.cache.len == 0)
doAssert(ac.isDirty == false)
ac.trie.rootHash
proc beginSavepoint*(ac: var AccountsCache): SavePoint =
@ -252,6 +263,7 @@ proc persistStorage(acc: RefAccount, db: TrieDatabaseRef) =
acc.account.storageRoot = accountTrie.rootHash
proc makeDirty(ac: AccountsCache, address: EthAddress, cloneStorage = true): RefAccount =
ac.isDirty = true
result = ac.getAccount(address)
if address in ac.savePoint.cache:
# it's already in latest savepoint
@ -391,9 +403,11 @@ proc deleteAccount*(ac: var AccountsCache, address: EthAddress) =
let acc = ac.getAccount(address)
acc.kill()
proc persist*(ac: var AccountsCache) =
proc persist*(ac: var AccountsCache, clearCache: bool = true) =
# make sure all savepoint already committed
doAssert(ac.savePoint.parentSavePoint.isNil)
var cleanAccounts = initHashSet[EthAddress]()
for address, acc in ac.savePoint.cache:
case acc.persistMode()
of Update:
@ -406,9 +420,19 @@ proc persist*(ac: var AccountsCache) =
ac.trie.put address, rlp.encode(acc.account)
of Remove:
ac.trie.del address
if not clearCache:
cleanAccounts.incl address
of DoNothing:
discard
acc.flags = acc.flags - resetFlags
if clearCache:
ac.savePoint.cache.clear()
else:
for x in cleanAccounts:
ac.savePoint.cache.del x
ac.isDirty = false
iterator storage*(ac: AccountsCache, address: EthAddress): (UInt256, UInt256) =
# beware that if the account not persisted,

View File

@ -44,7 +44,7 @@ proc processTransaction*(tx: Transaction, sender: EthAddress, vmState: BaseVMSta
if vmState.generateWitness:
vmState.accountDb.collectWitnessData()
vmState.accountDb.persist()
vmState.accountDb.persist(clearCache = false)
type
# TODO: these types need to be removed
@ -146,7 +146,7 @@ proc processBlock*(chainDB: BaseChainDB, header: BlockHeader, body: BlockBody, v
db.addBalance(header.coinbase, mainReward)
if vmState.generateWitness:
db.collectWitnessData()
db.persist()
db.persist(ClearCache in vmState.flags)
let stateDb = vmState.accountDb
if header.stateRoot != stateDb.rootHash:

View File

@ -43,6 +43,12 @@ proc newBaseVMState*(prevStateRoot: Hash256, header: BlockHeader,
new result
result.init(prevStateRoot, header, chainDB, tracerFlags)
proc newBaseVMState*(prevStateRoot: Hash256,
chainDB: BaseChainDB, tracerFlags: set[TracerFlags] = {}): BaseVMState =
new result
var header: BlockHeader
result.init(prevStateRoot, header, chainDB, tracerFlags)
proc setupTxContext*(vmState: BaseVMState, origin: EthAddress, gasPrice: GasInt, forkOverride=none(Fork)) =
## this proc will be called each time a new transaction
## is going to be executed
@ -55,6 +61,15 @@ proc setupTxContext*(vmState: BaseVMState, origin: EthAddress, gasPrice: GasInt,
vmState.chainDB.config.toFork(vmState.blockHeader.blockNumber)
vmState.gasCosts = vmState.fork.forkToSchedule
proc updateBlockHeader*(vmState: BaseVMState, header: BlockHeader) =
vmState.blockHeader = header
vmState.touchedAccounts.clear()
vmState.suicides.clear()
if EnableTracing in vmState.tracer.flags:
vmState.tracer.initTracer(vmState.tracer.flags)
vmState.logEntries = @[]
vmState.receipts = @[]
method blockhash*(vmState: BaseVMState): Hash256 {.base, gcsafe.} =
vmState.blockHeader.hash

View File

@ -19,6 +19,7 @@ type
VMFlag* = enum
ExecutionOK
GenerateWitness
ClearCache
BaseVMState* = ref object of RootObj
prevHeaders* : seq[BlockHeader]