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
Simplify gas metering #5121
Conversation
7d87464
to
48d1aa4
Compare
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.
48d1aa4
to
7166e24
Compare
runtime/near-vm-runner/src/tests.rs
Outdated
@@ -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; |
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.
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?
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.
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; |
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.
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?
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.
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 { |
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.
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
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.
Don't think that (checked) overflow in view mode is critical/important.
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.
Anyway, fixed it.
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.
Good work
|
077ea5f
to
5b8bedb
Compare
Results for me
That's sort-of the motivation here -- we can measurably speed the stuff up by just writing simpler code for the common case. |
Latest version gives |
@matklad this seems to be higher than what we projected. Do we know why that is the case? |
c6cbb1b
to
a3de3a5
Compare
It's only part of the optimization - second one is fully intrinsified counter on Wasmer side. |
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).
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.
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?
Sure, we haven't changed fast path since last measurement. |
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.
* 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>
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.