-
Notifications
You must be signed in to change notification settings - Fork 838
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
Unroll Untraced Execution #4540
Conversation
Add a second run-to-halt path used when there is no tracing. This path calls static final versions of select operations with the aim of avoiding the megamorphic dispatch of the original loop. Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>
Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>
Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>
~20-30% from prior PR, The hitch is that these are only for executions that do not involve tracing. This is standard for a mainnet production, but hedera depends on a tracer for some execution. I think I can re-work the trace interface to do what hedera needs.
Old (#4533)
New
|
Work isn't done, I should finish unrolling the basic arithmetic that hasn't changed since Frontier. Keeping the operations for complex operations won't have too bad an impact and preserves the customizability of the Besu EVM. |
the unrolling is a bit of pick and choose based off of cartevm testing Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>
Restore the tracing functionality by splitting it into pre and post execute tracing calls, removing the lambda based wrapping tracer. Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>
Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>
Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>
All the unrolling that adds performance instead of removing performance is in. PR is ready for review. Overview of changes:
|
@@ -20,9 +20,6 @@ | |||
import org.hyperledger.besu.evm.frame.MessageFrame; | |||
import org.hyperledger.besu.evm.gascalculator.GasCalculator; | |||
|
|||
import java.util.Optional; | |||
import java.util.OptionalLong; | |||
|
|||
import org.apache.tuweni.bytes.Bytes; | |||
|
|||
public class JumpiOperation extends AbstractFixedCostOperation { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was there not a similar benefit to a static OperationResult(xx,null) success response for the Jump operations?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, there wasn't. I was suprised.
@@ -34,8 +33,7 @@ public Operation.OperationResult executeFixedCostOperation( | |||
final MessageFrame frame, final EVM evm) { | |||
final Optional<Wei> maybeBaseFee = frame.getBlockValues().getBaseFee(); | |||
if (maybeBaseFee.isEmpty()) { | |||
return new Operation.OperationResult( | |||
OptionalLong.of(gasCost), Optional.of(ExceptionalHaltReason.INVALID_OPERATION)); | |||
return new Operation.OperationResult(gasCost, ExceptionalHaltReason.INVALID_OPERATION); | |||
} | |||
frame.pushStackItem(maybeBaseFee.orElseThrow()); | |||
return successResponse; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same q about static OperationResult(2, null) here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basefee gets overridden in downstream clients, so it cannot be optimized.
@@ -46,4 +48,21 @@ public Operation.OperationResult executeFixedCostOperation( | |||
|
|||
return successResponse; | |||
} | |||
|
|||
public static OperationResult staticOperation(final MessageFrame frame) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we not calling this from executeFixedCostOperation ? It looks like the EVM will call staticOperation from the case statement, so this is just a question of consistency
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
non-blocking feedback and questions, but looks great. It would be great to get this into the RC2 release today.
One other question - have you verified that the pre/post stack change to tracing API results in no tracing output diffs?
Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>
Yes, we have unit tests for the tracers and it comes out the same. That was what two hours of the work time was spent doing, figuring out what fields had to be read pre-exec and stored in the tracer and what is read post-exec for the output. |
Overview of changes: * Remove vestigial log tracing. We will never use it in production and standard json tracing gets us what we need * Reduce use of lambdas and optionals. Reads great, translates into a 10% perf hit in a tight loop. * Unroll operation loop in some cases. Those are (a) ops that haven't changed in any way since Frontier (b) ops not overridden in downstream uses and (c) operations that translate into short static executions. This has the longest tendrils as it is enabled by operations exposing static methods to do their work. * Refactoring of the operationTracer. The single, lambda consuming traceExecution method was a barrier to performance. It has been replaced with tracePreExecution and tracePostExecution. Look at DebugOperationTracer to see how traces that need to operate on both sides of the operation can be handled with this API. Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com> Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
Overview of changes: * Remove vestigial log tracing. We will never use it in production and standard json tracing gets us what we need * Reduce use of lambdas and optionals. Reads great, translates into a 10% perf hit in a tight loop. * Unroll operation loop in some cases. Those are (a) ops that haven't changed in any way since Frontier (b) ops not overridden in downstream uses and (c) operations that translate into short static executions. This has the longest tendrils as it is enabled by operations exposing static methods to do their work. * Refactoring of the operationTracer. The single, lambda consuming traceExecution method was a barrier to performance. It has been replaced with tracePreExecution and tracePostExecution. Look at DebugOperationTracer to see how traces that need to operate on both sides of the operation can be handled with this API. Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>
PR description
Add a second run-to-halt path used when there is no tracing. This path calls static final versions of select operations with the aim of avoiding the megamorphic dispatch of the original loop.
Fixed Issue(s)
Documentation
doc-change-required
label to this PR ifupdates are required.
Changelog