Skip to content

EVM: Further dispatch refactoring #876

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

Merged
merged 6 commits into from
Nov 29, 2022
Merged

Conversation

vyzo
Copy link
Contributor

@vyzo vyzo commented Nov 29, 2022

Ever so slightly faster (0.5% improvement over next head in simplecoin), but much nicer code.
And if we turn off overflow checks, it's a 3.24% improvement.

@vyzo vyzo requested a review from Stebalien November 29, 2022 08:14
@codecov-commenter
Copy link

Codecov Report

Merging #876 (586eb22) into next (5a4b15b) will increase coverage by 0.02%.
The diff coverage is 94.30%.

❗ Current head 586eb22 differs from pull request most recent head d848298. Consider uploading reports for the commit d848298 to get more accurate results

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             next     #876      +/-   ##
==========================================
+ Coverage   87.10%   87.12%   +0.02%     
==========================================
  Files         126      126              
  Lines       23278    23346      +68     
==========================================
+ Hits        20276    20341      +65     
- Misses       3002     3005       +3     
Impacted Files Coverage Δ
actors/evm/src/interpreter/instructions/mod.rs 81.48% <81.25%> (-0.96%) ⬇️
actors/evm/src/interpreter/execution.rs 86.36% <87.50%> (-2.17%) ⬇️
...ors/evm/src/interpreter/instructions/arithmetic.rs 91.45% <100.00%> (+2.18%) ⬆️
actors/evm/src/interpreter/instructions/bitwise.rs 75.34% <100.00%> (+3.03%) ⬆️
actors/cron/src/lib.rs 89.65% <0.00%> (-3.45%) ⬇️
state/src/check.rs 86.24% <0.00%> (-0.27%) ⬇️
actors/miner/src/testing.rs 92.05% <0.00%> (+0.24%) ⬆️

Copy link
Member

@Stebalien Stebalien left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some nits but we can try those in a followup patch.

Comment on lines +129 to 133
match instructions::$ins($m) {
Ok($res) => $body,
Err(err) => {
$m.exit = Some(err);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be interested to see if the following were faster:

$m.exit = instructions::$ins($m).err()
$m.pc += 1; // when actually changing the PC.

In all cases. Basically, avoid the branches.

Of course, that might actually be slower in terms of gas used. But I'm still curious.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, i will try it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

err branches on its own perhaps? Or is it a vtable thing?

I am skeptical whether this would be any faster, and it is also somewhat harder to reason about.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, there is an assignment that doesnt need to happen 99.9% of the time; potentially just as bas as a correctly predicted branch or worse.

Comment on lines +162 to +166
self.step();

if self.exit.is_some() {
break;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm. Can we move this condition to the top to reduce the number of breaks?

I.e.:

while self.exit.is_none() && self.pc < self.bytecode.len() {
    self.step();
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, somewhat prettier; my way is more explicit however

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some more thoughts here: the current code is optimal in terms of branches.

Initially, exit is known to be None (initial state invariant), but the code may be empty so we need to check pc against the bound.
Then we execute the instruction, which may change exit, at which point we check it and loop.

No matter how you look at it, the prettier variant will execute one more check/possible branch than the current code.

So i suggest we keep it as is.

Comment on lines +177 to +181
let op = OpCode::try_from(self.bytecode[self.pc]);
match op {
Ok(op) => Self::JMPTABLE[op as usize](self),
Err(err) => self.exit = Some(err),
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of checking if PC is "in bounds above and inside step, we can just check inside step:

Suggested change
let op = OpCode::try_from(self.bytecode[self.pc]);
match op {
Ok(op) => Self::JMPTABLE[op as usize](self),
Err(err) => self.exit = Some(err),
}
match self.bytecode.get(self.pc).ok_or(StatusCode::Success).map(OpCode::try_from) {
Ok(op) => Self::JMPTABLE[op as usize](self),
Err(err) => self.exit = Some(err),
}

Then remove the self.pc < self.bytecode.len() check above.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably also use unsafe when accessing the jumptable. That I'm happy with given that we know it's safe.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll try those too.

Comment on lines +380 to +381
m.reverted = true;
m.exit = Some(StatusCode::Success);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

future: maybe StatusCode::Reverted?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we have multiple ways to revert, yeah.

@@ -137,36 +134,90 @@ mod test {
}
}

pub fn ins_add(s: &mut Stack) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we should probably just fix the tests to call the instructions directly. We only tested the instructions with a proper stack because we had no other way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, a chore for when we have nothing better to do.

@Stebalien Stebalien merged commit 8a5a26b into next Nov 29, 2022
@Stebalien Stebalien deleted the next-moar-dispatch-refactor branch November 29, 2022 17:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants