Skip to content
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

Simplify gas metering #5121

Merged
merged 24 commits into from Nov 8, 2021
Merged

Simplify gas metering #5121

merged 24 commits into from Nov 8, 2021

Conversation

olonho
Copy link
Contributor

@olonho olonho commented Nov 3, 2021

Rework the logic of gas counting to ensure that there's a single limit to be compared with.
It allows to speed up gas metering significantly and opens possibility of intrinsified gas counting.

Rework the logic of gas counting to ensure that there's a single limit to be compared with.
It allows to speed up gas metering significantly and opens possibility of intrinsified gas counting.
@olonho olonho marked this pull request as ready for review November 4, 2021 12:39
@@ -63,7 +63,8 @@ fn make_simple_contract_call_with_gas_vm(
let mut fake_external = MockedExternal::new();
let mut context = create_context(vec![]);
context.prepaid_gas = prepaid_gas;
let config = VMConfig::default();
let mut config = VMConfig::default();
config.limit_config.max_gas_burnt = prepaid_gas;
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems that this makes near-vm-runner tests less useful, as they now can only hit the cases where the two limits are identical. Can we keep the original version?

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.

// if max_gas_burnt == prepaid_gas we must use GasExceeded error.
if new_burnt_gas > self.max_gas_burnt && self.max_gas_burnt != self.prepaid_gas {
self.fast_counter.burnt_gas = self.max_gas_burnt;
self.promises_gas = 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

If I comment-out this line, the tests seem to pass. That's suspicious. Can we add a test that shows that this line is needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can add this line when making protocol change.

pub fn burn_gas(&mut self, value: Gas) -> Result<()> {
let new_burnt_gas =
self.fast_counter.burnt_gas.checked_add(value).ok_or(HostError::IntegerOverflow)?;
if new_burnt_gas <= self.fast_counter.gas_limit {
Copy link
Contributor

Choose a reason for hiding this comment

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

Theoretically in view mode we could have promised something close to u64::max() gas by now and with new burnt gas that could have overflown integer in deduct_gas. Not sure if we care enough about this case

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Don't think that (checked) overflow in view mode is critical/important.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Anyway, fixed it.

Copy link
Contributor

@EgorKulikov EgorKulikov left a comment

Choose a reason for hiding this comment

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

Good work

@olonho
Copy link
Contributor Author

olonho commented Nov 4, 2021

WasmInstruction 442_940

@matklad
Copy link
Contributor

matklad commented Nov 4, 2021

Results for me

Before:
WasmInstruction                                       709_273
After:
WasmInstruction                                       459_905

That's sort-of the motivation here -- we can measurably speed the stuff up by just writing simpler code for the common case.

@olonho
Copy link
Contributor Author

olonho commented Nov 5, 2021

Latest version gives WasmInstruction 442_952.

matklad added a commit to matklad/nearcore that referenced this pull request Nov 5, 2021
@bowenwang1996
Copy link
Collaborator

Results for me

Before:
WasmInstruction                                       709_273
After:
WasmInstruction                                       459_905

That's sort-of the motivation here -- we can measurably speed the stuff up by just writing simpler code for the common case.

@matklad this seems to be higher than what we projected. Do we know why that is the case?

@olonho
Copy link
Contributor Author

olonho commented Nov 8, 2021

Results for me

Before:
WasmInstruction                                       709_273
After:
WasmInstruction                                       459_905

That's sort-of the motivation here -- we can measurably speed the stuff up by just writing simpler code for the common case.

@matklad this seems to be higher than what we projected. Do we know why that is the case?

It's only part of the optimization - second one is fully intrinsified counter on Wasmer side.

near-bulldozer bot pushed a commit that referenced this pull request Nov 8, 2021
Add vm logic tests targeting gas counting logic specifically. In particular, `test_cant_burn_more_than_max_gas_burnt_gas` I believe passes the current master, but fails with #5121 (which passes all other tests).
Copy link
Contributor

@matklad matklad left a comment

Choose a reason for hiding this comment

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

I think this now preserves behavior, so that's good to go!

I am still a little bit on the fence about adding #[repr(C)] bit in this PR and not in the one which actually enables wasmer change, but we can always remove that later if it proves to be unnecessary.

Could you confirm that the this final version with all bugs fixed still gives us an improvement?

@olonho
Copy link
Contributor Author

olonho commented Nov 8, 2021

Sure, we haven't changed fast path since last measurement.

@olonho olonho merged commit 468d806 into master Nov 8, 2021
@olonho olonho deleted the simplify_counter branch November 8, 2021 17:29
olonho added a commit to near/wasmer that referenced this pull request Nov 12, 2021
As our measurements show that gas counting is significant part of execution cost,
we need to optimize it as much as possible. This PR provides support for shared
fast gas counter structure, second part is implemented in near/nearcore#5121

Fast gas counter has three fields: current counter, limit and op cost. When we see call to host
function called `gas` with single argument we do not actually emit such a call, but instead
emit inline instruction sequence to increment gas counter per requested amount and if limit is hit -
GasExceed trap happens.

For fast gas counter to work VM embedder shall provide gas counter context, and VM will trap on call
to `gas` function if such context wasn't provided.
olonho added a commit to near/wasmer that referenced this pull request Nov 12, 2021
* Gas intrinsic support

As our measurements show that gas counting is significant part of execution cost,
we need to optimize it as much as possible. This PR provides support for shared
fast gas counter structure, second part is implemented in near/nearcore#5121

Fast gas counter has three fields: current counter, limit and op cost. When we see call to host
function called `gas` with single argument we do not actually emit such a call, but instead
emit inline instruction sequence to increment gas counter per requested amount and if limit is hit -
GasExceed trap happens.

For fast gas counter to work VM embedder shall provide gas counter context, and VM will trap on call
to `gas` function if such context wasn't provided.


Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
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.

None yet

5 participants