Skip to content

Redesign async EVM termination #23969

@chfast

Description

@chfast

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.

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions