Closed chfast closed 1 month ago
I implemented this PoC where code is analyzed when getting from "db" and kept in this "executable" form in IntraBlockState
. Now checking if this is correct by Mainnet sync... https://github.com/erigontech/silkworm/pull/2097
With the original LRU cache of code analysis the analyze()
is close to 0% in profile. This modification bumps it to ~1%.
This also doesn't solve the inefficient DB/mdbx interface where to pad the code I need a full copy of it. Having the full copy if the code the mdbx paged original code is wasted.
The conclusion from the Mainnet execution sync benchmark and manual profiling is the Code Analysis cache is effective. The cache can be also used for code, see https://github.com/erigontech/silkworm/issues/2382.
First of all, an account code is almost exclusively used for execution. It may be used as data source via
EXTCODECOPY
but this instruction is rarely used in practice (see example stats).When a deployed code is loaded from mdbx it is kept by reference (e.g. in
IntraBlockState::existing_code_
). This is because the db maps its storage to memory and accessing such code is valid until next commit (?). This works as a cache layer and saves a copy.However, there are some problems related to the maintaining the code this way.
The
existing_code_
lives only for a single block because it's lifetime is bounded byExecutionProcessor
inBlockchain::execute_block()
. Maybe this should be extended until the next commit?The evmone cannot use the code in this form. It needs additional preprocessing of the code: padding (for more efficient interpreter loop) and jumpdest analysis.
Silkworm has a LRU cache of size 5000 of such preprocessed code in
EVM::analysis_cache
used inEVM::execute_with_baseline_interpreter
.Potential improvement: drop LRU cache
After preprocessing the original code is useless. We can do the preprocessing when loading from db and keep the preprocessed form in the
existing_code_
. This removes the need for LRU cache. However, to my knowledge there is no way to inform mdbx that the value is not needed any more and can be unloaded from memory.Potential improvement: preprocess code on deployment
More advanced approach is to preprocess the code when it is being deployed (contract creation) and store the preprocessed version in mdbx. Here we can some sub-options: