Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

statemanager: cache and other refactors #3569

Merged
merged 27 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
fa3c2ec
Revert "statemanager: refactor logic into capabilities (#3554)"
gabrocheleau Aug 7, 2024
bd1f237
statemanager: refactor modifyAccountFields
gabrocheleau Aug 7, 2024
d5aaf30
statemanager: adjust return statements
gabrocheleau Aug 7, 2024
533fa8c
statemanager: refactor separate caches into caches class
gabrocheleau Aug 9, 2024
31c94af
chore: merge with master
gabrocheleau Aug 9, 2024
bba928b
statemanager: fix shallow copy logic
gabrocheleau Aug 9, 2024
a04158d
client: fix vmexecution statemanager cache opts
gabrocheleau Aug 9, 2024
2431594
statemanager: refactor some capabilities to caches methods
gabrocheleau Aug 9, 2024
814b9f7
statemanager: fix tests
gabrocheleau Aug 9, 2024
2439219
statemanager: refactor caches into optional opt passed in directly to…
gabrocheleau Aug 9, 2024
4c6240f
statemanager: adjust tests with refactored caches
gabrocheleau Aug 9, 2024
5e1666d
client: adjust vm execution with update cache
gabrocheleau Aug 9, 2024
c754eac
vm: fix vm tests
gabrocheleau Aug 9, 2024
5d4895c
vm: adjust test runners with non-default caches
gabrocheleau Aug 9, 2024
888b20e
statemanager: simplify handling of deactivate
gabrocheleau Aug 9, 2024
905a52e
statemanager: remove redundant checks
gabrocheleau Aug 9, 2024
f30288a
statemanager: remove non null asesertion
gabrocheleau Aug 9, 2024
ba00837
statemanager: remove cache opt from key naming
gabrocheleau Aug 10, 2024
c037ae2
statemanager: refactor rpc state manager to use caches
gabrocheleau Aug 11, 2024
fdcdb36
statemanager: fix rpc state manager tests
gabrocheleau Aug 11, 2024
3d93587
client: vmexecution cache stats refactor
gabrocheleau Aug 11, 2024
48baee3
Merge remote-tracking branch 'origin/master' into statemanager/capabi…
acolytec3 Aug 12, 2024
f0b66bf
Merge branch 'master' into statemanager/capabilities-refactor
acolytec3 Aug 12, 2024
5f4c253
statemanageR: updategetproof json-rpc call format
gabrocheleau Aug 12, 2024
7fe21fd
statemanager: remove deactivate from caches
gabrocheleau Aug 12, 2024
4864383
client: remove deactivate from vm execution instantiation
gabrocheleau Aug 12, 2024
b6ee97b
Merge branch 'statemanager/capabilities-refactor' of https://github.c…
gabrocheleau Aug 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 27 additions & 27 deletions packages/client/src/execution/vmexecution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@ import {
DBSetHashToNumber,
DBSetTD,
} from '@ethereumjs/blockchain'
import { CacheType, ConsensusType, Hardfork } from '@ethereumjs/common'
import { ConsensusType, Hardfork } from '@ethereumjs/common'
import { MCLBLS, RustBN254 } from '@ethereumjs/evm'
import { getGenesis } from '@ethereumjs/genesis'
import { DefaultStateManager, StatelessVerkleStateManager } from '@ethereumjs/statemanager'
import {
CacheType,
Caches,
DefaultStateManager,
StatelessVerkleStateManager,
} from '@ethereumjs/statemanager'
import { createTrie } from '@ethereumjs/trie'
import {
BIGINT_0,
Expand Down Expand Up @@ -35,7 +40,6 @@ import { ReceiptsManager } from './receipt.js'

import type { ExecutionOptions } from './execution.js'
import type { Block } from '@ethereumjs/block'
import type { Trie } from '@ethereumjs/trie'
import type { PrefixedHexString } from '@ethereumjs/util'
import type { RunBlockOpts, TxReceipt } from '@ethereumjs/vm'

Expand Down Expand Up @@ -160,21 +164,20 @@ export class VMExecution extends Execution {
const stateManager = new DefaultStateManager({
trie,
prefixStorageTrieKeys: this.config.prefixStorageTrieKeys,
accountCacheOpts: {
deactivate: false,
type: CacheType.LRU,
size: this.config.accountCache,
},
storageCacheOpts: {
deactivate: false,
type: CacheType.LRU,
size: this.config.storageCache,
},
codeCacheOpts: {
deactivate: false,
type: CacheType.LRU,
size: this.config.codeCache,
},
caches: new Caches({
account: {
type: CacheType.LRU,
size: this.config.accountCache,
},
storage: {
type: CacheType.LRU,
size: this.config.storageCache,
},
code: {
type: CacheType.LRU,
size: this.config.codeCache,
},
}),
common: this.config.chainCommon,
})

Expand Down Expand Up @@ -1059,25 +1062,22 @@ export class VMExecution extends Execution {

stats() {
if (this._statsVM instanceof DefaultStateManager) {
const sm = this._statsVM.stateManager as any
const disactivatedStats = { size: 0, reads: 0, hits: 0, writes: 0 }
const sm = this._statsVM.stateManager as DefaultStateManager
const deactivatedStats = { size: 0, reads: 0, hits: 0, writes: 0 }
let stats
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
stats = !sm._accountCacheSettings.deactivate ? sm._accountCache.stats() : disactivatedStats
stats = sm['_caches']?.account?.stats() ?? deactivatedStats
this.config.logger.info(
`Account cache stats size=${stats.size} reads=${stats.reads} hits=${stats.hits} writes=${stats.writes}`,
)
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
stats = !sm._storageCacheSettings.deactivate ? sm._storageCache.stats() : disactivatedStats
stats = sm['_caches']?.storage?.stats() ?? deactivatedStats
this.config.logger.info(
`Storage cache stats size=${stats.size} reads=${stats.reads} hits=${stats.hits} writes=${stats.writes}`,
)
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
stats = !sm._codeCacheSettings.deactivate ? sm._codeCache.stats() : disactivatedStats
stats = sm['_caches']?.code?.stats() ?? deactivatedStats
this.config.logger.info(
`Code cache stats size=${stats.size} reads=${stats.reads} hits=${stats.hits} writes=${stats.writes}`,
)
const tStats = (sm._trie as Trie).database().stats()
const tStats = sm['_trie'].database().stats()
this.config.logger.info(
`Trie cache stats size=${tStats.size} reads=${tStats.cache.reads} hits=${tStats.cache.hits} ` +
`writes=${tStats.cache.writes} readsDB=${tStats.db.reads} hitsDB=${tStats.db.hits} writesDB=${tStats.db.writes}`,
Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/rpc/modules/eth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ import type { EthProtocol } from '../../net/protocol/index.js'
import type { FullEthereumService, Service } from '../../service/index.js'
import type { RpcTx } from '../types.js'
import type { Block, JsonRpcBlock } from '@ethereumjs/block'
import type { Proof } from '@ethereumjs/common'
import type { Log } from '@ethereumjs/evm'
import type { Proof } from '@ethereumjs/statemanager'
import type {
FeeMarketEIP1559Transaction,
LegacyTransaction,
Expand Down
31 changes: 0 additions & 31 deletions packages/common/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,35 +169,4 @@ export interface StateManagerInterface {
*/
clearCaches(): void
shallowCopy(downlevelCaches?: boolean): StateManagerInterface

/*
* Cache properties
*/
_accountCache?: Cache
_storageCache?: Cache
_codeCache?: Cache

_accountCacheSettings?: CacheSettings
_storageCacheSettings?: CacheSettings
_codeCacheSettings?: CacheSettings
}

/**
* Cache related
*/
export enum CacheType {
LRU = 'lru',
ORDERED_MAP = 'ordered_map',
}

export type CacheSettings = {
deactivate: boolean
type: CacheType
size: number
}

interface Cache {
checkpoint(): void
commit(): void
revert(): void
}
6 changes: 3 additions & 3 deletions packages/statemanager/src/cache/account.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { CacheType } from '@ethereumjs/common'
import { bytesToUnprefixedHex } from '@ethereumjs/util'
import { OrderedMap } from '@js-sdsl/ordered-map'
import debugDefault from 'debug'
import { LRUCache } from 'lru-cache'

import { Cache } from './cache.js'
import { CacheType } from './types.js'

import type { CacheOpts } from './types.js'
import type { Account, Address } from '@ethereumjs/util'
Expand Down Expand Up @@ -68,14 +68,14 @@ export class AccountCache extends Cache {
put(
address: Address,
account: Account | undefined,
couldBeParitalAccount: boolean = false,
couldBePartialAccount: boolean = false,
): void {
const addressHex = bytesToUnprefixedHex(address.bytes)
this._saveCachePreState(addressHex)
const elem = {
accountRLP:
account !== undefined
? couldBeParitalAccount
? couldBePartialAccount
? account.serializeWithPartialInfo()
: account.serialize()
: undefined,
Expand Down
89 changes: 89 additions & 0 deletions packages/statemanager/src/cache/caches.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { AccountCache } from './account.js'
import { CodeCache } from './code.js'
import { StorageCache } from './storage.js'
import { CacheType, type CachesStateManagerOpts } from './types.js'

import type { CacheOpts } from './types.js'
import type { Address } from '@ethereumjs/util'

export class Caches {
account?: AccountCache
code?: CodeCache
storage?: StorageCache

settings: Record<'account' | 'code' | 'storage', CacheOpts>

constructor(opts: CachesStateManagerOpts = {}) {
const accountSettings = {
type: opts.account?.type ?? CacheType.ORDERED_MAP,
size: opts.account?.size ?? 100000,
}

const codeSettings = {
type: opts.code?.type ?? CacheType.ORDERED_MAP,
size: opts.code?.size ?? 20000,
}

const storageSettings = {
type: opts.storage?.type ?? CacheType.ORDERED_MAP,
size: opts.storage?.size ?? 20000,
}

this.settings = {
account: accountSettings,
code: codeSettings,
storage: storageSettings,
}

if (this.settings.account.size !== 0) {
this.account = new AccountCache({
size: this.settings.account.size,
type: this.settings.account.type,
})
}

if (this.settings.code.size !== 0) {
this.code = new CodeCache({
size: this.settings.code.size,
type: this.settings.code.type,
})
}

if (this.settings.storage.size !== 0) {
this.storage = new StorageCache({
size: this.settings.storage.size,
type: this.settings.storage.type,
})
}
}

checkpoint() {
this.account?.checkpoint()
this.storage?.checkpoint()
this.code?.checkpoint()
}

clear() {
this.account?.clear()
this.storage?.clear()
this.code?.clear()
}

commit() {
this.account?.commit()
this.storage?.commit()
this.code?.commit()
}

deleteAccount(address: Address) {
this.code?.del(address)
this.account?.del(address)
this.storage?.clearStorage(address)
}

revert() {
this.account?.revert()
this.storage?.revert()
this.code?.revert()
}
}
2 changes: 1 addition & 1 deletion packages/statemanager/src/cache/code.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { CacheType } from '@ethereumjs/common'
import { bytesToUnprefixedHex } from '@ethereumjs/util'
import { OrderedMap } from '@js-sdsl/ordered-map'
import debugDefault from 'debug'
import { LRUCache } from 'lru-cache'

import { Cache } from './cache.js'
import { CacheType } from './types.js'

import type { CacheOpts } from './types.js'
import type { Address } from '@ethereumjs/util'
Expand Down
1 change: 1 addition & 0 deletions packages/statemanager/src/cache/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './account.js'
export * from './caches.js'
export * from './code.js'
export * from './originalStorageCache.js'
export * from './storage.js'
Expand Down
2 changes: 1 addition & 1 deletion packages/statemanager/src/cache/storage.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { CacheType } from '@ethereumjs/common'
import { bytesToUnprefixedHex, hexToBytes } from '@ethereumjs/util'
import { OrderedMap } from '@js-sdsl/ordered-map'
import debugDefault from 'debug'
import { LRUCache } from 'lru-cache'

import { Cache } from './cache.js'
import { CacheType } from './types.js'

import type { CacheOpts } from './types.js'
import type { Address } from '@ethereumjs/util'
Expand Down
32 changes: 31 additions & 1 deletion packages/statemanager/src/cache/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,36 @@
import type { CacheType } from '@ethereumjs/common'
export enum CacheType {
LRU = 'lru',
ORDERED_MAP = 'ordered_map',
}

export interface CacheOpts {
/**
* Size of the cache (only for LRU cache)
*
* Default: 100000 (account cache) / 20000 (storage cache) / 20000 (code cache)
*
* Note: the cache/trie interplay mechanism is designed in a way that
* the theoretical number of max modified accounts between two flush operations
* should be smaller than the cache size, otherwise the cache will "forget" the
* old modifications resulting in an incomplete set of trie-flushed accounts.
*/
size: number
/**
* Cache type to use.
*
* Available options:
*
* ORDERED_MAP: Cache with no fixed upper bound and dynamic allocation,
* use for dynamic setups like testing or similar.
*
* LRU: LRU cache with pre-allocation of memory and a fixed size.
* Use for larger and more persistent caches.
*/
type: CacheType
}

export interface CachesStateManagerOpts {
account?: Partial<CacheOpts>
code?: Partial<CacheOpts>
storage?: Partial<CacheOpts>
}
Loading
Loading