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

Idea: Gas cost split for background compilation #7625

Open
Ekleog opened this issue Sep 16, 2022 · 1 comment
Open

Idea: Gas cost split for background compilation #7625

Ekleog opened this issue Sep 16, 2022 · 1 comment
Labels
A-contract-runtime Area: contract compilation and execution, virtual machines, etc T-contract-runtime Team: issues relevant to the contract runtime team

Comments

@Ekleog
Copy link
Contributor

Ekleog commented Sep 16, 2022

This is a tentative tracking issue describing a development idea. It is not a project we actually started working on.

Introduction

Right now, we charge for some amount of gas per action. We have a 300Tgas limit per transaction, with a 1.3Pgas limit per chunk (1Pgas plus "spillover" that can currently happen if the last receipt goes beyond 1Pgas). (Reminder: 1Tgas accounts for 1ms of computation time, 1Pgas is 1s)

However, we would like to be able to deploy smart contracts that take more than 300ms to compile, and ideally have contract deployment be cheaper at the same time.

High-level design

In order to do this, this design suggests that we split the gas cost in two types: "main thread CPU time" and "background thread CPU time". We could then use a background thread to compile, and charge for the compilation with background gas.

This has no impact on UX, as contract compilation is charged without the user having to ever know how it is computed, and the user only really cares about the amount of near tokens consumed.

Mid-level design

  • We split gas costs in two kinds: either "main thread gas cost" or "background thread gas cost"
  • Main thread gas cost still has a 300Tgas limit per transaction, with a 1(.3)Pgas limit per chunk
  • Background thread gas cost now has a higher limit per transaction (1Pgas?), but still has a 1Pgas limit per chunk (where we should make sure we never actually go above 1Pgas, as 2Pgas would be too much)
  • Contract compilation is relegated to a background thread, and costs a bit of main thread gas (to account for task creation) and a lot of background thread gas
  • We need to decide on a gas cost computation formula. In order not to affect current gas computation we would probably want to have it be something like $\text{gas} = (α\ \text{mainThreadGas} + β\ \text{bgThreadGas})$ and then changing the gas computation formula so it's the same for $\text{gas}/α$

Unresolved questions

  • What about calling a function just after deploying a contract, in the same block? (Or even if contract deployment is the last receipt of the previous block and the function call the first receipt of the next block, which would cause the same issues).
    Can we just disallow this?

Related changes that will probably happen as by-products

The 1.3Pgas limit per chunk is currently a byproduct of a 1Pgas limit where we allow the last receipt to go overboard by its size. This is wrong and we should probably decide whether we actually want the limit to be 1Pgas or 1.3Pgas. Given we probably do not want to reduce the number of transactions per chunk, my guess would be we will stay with 1.3Pgas.

Right now, our behavior is that we have a 1.3Pgas limit, and as soon as less than 300Tgas remain we stop executing receipts, fearing that they may go overboard.

However, once we actually define the gas limit as 1.3Pgas, we can fill chunk more: so long as there is gas left, we can continue iterating over the receipts, and just execute them until we find one that would actually make us go beyond the 1.3Pgas limit: as not all receipts actually consume 300Tgas (or have 300Tgas attached for function call receipts), this would increase our block fullness and so number of transactions per block.

A further change would be to allow reordering receipts (say we're currently at 1.1Pgas and we have in the receipt queue first a 250Tgas receipt then a 150Tgas receipt, we could execute the 150Tgas receipt but it's after in the queue so even with the currently-proposed related change it wouldn't be executed), but given this would change receipt ordering it's not something I currently suggest.

Future improvements

Splitting the gas cost this way sets up the whole infrastructure for splitting gas costs further. In particular, it paves the way to splitting IO gas costs out, so that we can parallelize IO operations and CPU operations during both receipt and contract execution.

However, given taking full advantage of splitting IO gas costs out would also require contract-guided prefetching to take full advantage of it (and have an impact on UI as contract calls would then need to attach two kinds of gas), this is kept as future work that may or may not happen unrelated to this specific idea.

Planned process

  • Investigate the idea some more to verify whether we actually want to do this
  • Update the planned process accordingly
@Ekleog-NEAR Ekleog-NEAR added C-epic Category: an epic A-contract-runtime Area: contract compilation and execution, virtual machines, etc T-contract-runtime Team: issues relevant to the contract runtime team labels Sep 16, 2022
@Ekleog-NEAR Ekleog-NEAR changed the title Tracking issue: Gas cost split for background compilation Idea: Gas cost split for background compilation Sep 16, 2022
@jakmeier
Copy link
Contributor

Thanks for this write-up! As discussed, I agree this is an interesting potential solution to the problem of compiling large contracts.

The problem with calling the contract while it is being compiled in the background is a tricky one. I only see one option right now. We would have to disallow function calls after deployments to the same account in the same receipt, and perhaps also rearrange receipt ordering to make sure the gap between such receipts is large enough. Not only is this a big change, I also find it difficult to assess what innovation would be stifled by such a limitation.
I think all of this should be weighed against the alternative that would be disallowing compiling large contracts.

I don't think we should link this to changing the algorithm to fill blocks, I don't see a reason why they should be related. Investigating just the gas cost split on its own is complex enough. And the other change could be done independently.

@Ekleog-NEAR Ekleog-NEAR removed the C-epic Category: an epic label Sep 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-contract-runtime Area: contract compilation and execution, virtual machines, etc T-contract-runtime Team: issues relevant to the contract runtime team
Projects
None yet
Development

No branches or pull requests

3 participants