-
Notifications
You must be signed in to change notification settings - Fork 21.5k
Description
There is an atomic load inside the EVM loop that checks if execution should be terminated before reaching the end. The idea being that it’s nice if we can abort an infinite loop over rpc, after the rpc-call times out.
go-ethereum/core/vm/interpreter.go
Lines 183 to 188 in 66ee942
| steps := 0 | |
| for { | |
| steps++ | |
| if steps%1000 == 0 && atomic.LoadInt32(&in.evm.abort) != 0 { | |
| break | |
| } |
CPU profile
. . 182: steps := 0
. . 183: for {
120ms 120ms 184: steps++
120ms 120ms 185: if steps%1000 == 0 {
. . 186: if atomic.LoadInt32(&in.evm.abort) != 0 {
. . 187: break
. . 188: }
. . 189: }
The atomic itself is not a problem, but tracking steps is. This consumes at least one additional register.
Easy quick improvements is to change the condition to steps%1024. https://godbolt.org/z/esfhf3EhW
Considering the feature is only to terminate long running looped EVM code, I propose to track jumps instead of steps. We can have in.numJumps field which will be bumped in opJump() and opJumpi(). And atomic flag will be checked every some number of jumps. The numJumps does not need to be ever reset if the condition is e.g. numJumps % 64 == 0. Also check what is the overhead of checking the atomic flag on every jump.