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

Add option to limit CPU usage #422

Closed
codefromthecrypt opened this issue Mar 31, 2022 · 12 comments
Closed

Add option to limit CPU usage #422

codefromthecrypt opened this issue Mar 31, 2022 · 12 comments
Assignees

Comments

@codefromthecrypt
Copy link
Contributor

split from #417 requested by @inkeliz

Also, would be interesting to limit the CPU usage, but I think it's hard to track the CPU usage, that could be more useful when WASM supports thread directly.

Prior art

Related

#421 could be a similar or the same implementation, as if you have a concept of a runtime-wide credit you can deplete it to stop all commands, though what happens when out of credit is likely different (exit instead of pause)

@codefromthecrypt
Copy link
Contributor Author

here's something from ewasm that may be relevant https://ewasm.readthedocs.io/en/mkdocs/determining_wasm_gas_costs/

@codefromthecrypt
Copy link
Contributor Author

@JanFalkin do you mind commenting on which metering/limiting features you need and any links if a standard practice?

@JanFalkin
Copy link

@codefromthecrypt Our need was for actual billing for our content-fabric. Things we serve up and the effort to do so as a function of bitcode. Ultimately I would like to know cpu and memory usage of the bitcode itself. I was hoping just for any type of metering even if they were pseudo cycles that had a basis in reality. This was one of the main reasons I was heading for Wasmer, as they have metering built in at an opcode level. So you can submit a list of "costs" per wasm opcode and Wasmer will track this as a measure of work done. I did not look that carefully at whether Wasmer was using a Cranelift feature or it had implemented it's own opcode metering. As for limiting execution, it would be very interesting, but it was not our must have at release features.

@pims
Copy link
Contributor

pims commented Feb 2, 2023

👋 , having used the fuel feature in Wasmtime linked above, that's also something that I would love to be able to use in wazero. The main benefits would:

  1. guarantee that a process will eventually stop – when running out of fuel
  2. it could provide the necessary hook points to yield to the host to be able to interrupt execution based on external signals.

@codefromthecrypt
Copy link
Contributor Author

thanks @pims I can see some related pull requests on wasmtime, and also they had another impl iirc also. sounds like the status quo "fuel" one is good enough. there are differences between this and wasmer, and also its inspiration. I wonder if anyone has it speced or this will be the only thing they decide not to make into a new wasm/wasi spec? :D

@codefromthecrypt
Copy link
Contributor Author

@evacchi wanna take this from analysis to some form of impl once we're through the 1.0 stdlib/wasi gauntlet?

@springrain
Copy link

springrain commented Jun 22, 2023

Set gas for each WASM instruction, support host function custom setting gas value, so that the gas used by wasm execution is calculated, and if the gas limit is exceeded, wasm will automatically exit, which will be simpler than calculating the CPU and other methods, and also meet the basic needs

@iansmith
Copy link

@springrain For those of of us that want to use this as more of a "metering" then your minimal feature isn't quite enough. Perhaps a WithGasExhaustedCallback(...func name..) which is called when gas is exhausted and can return either true or false with false meaning "kill the wasm program".

The reason this is so important to folks like me is precisely because we want to kill programs that exhaust their gas ... but we want to have some mode of operational testing so folks can "get a notice" when their gas is exhausted, but not exit. Without this, the exit of the program is very hard to avoid as you would have no data about what you can/cannot do without running out of gas.

@springrain
Copy link

springrain commented Jun 25, 2023

@iansmith Calculating gas is the core function, and the exit logic of gas exhaustion can add a function configuration WithGasExhaustedCallback(...func name..)

@codefromthecrypt
Copy link
Contributor Author

There are some technical notes in #1108 as to why we closed this issue. This will remain closed until we have new information. It won't be re-opened without new information.

@l0nax
Copy link

l0nax commented Jul 26, 2023

@codefromthecrypt I've read #1108 and any related issues, but I still don't understand what's blocking this implementation.
Especially everything related to the gas/ cost implementation.

#1108 mentions that the newly added flag (WithCloseOnContextDone) may be used to implement such a cost thing. But as of now, I don't see a possibility to implement it – there's is no interpretation middleware/ hook option; no statistics; etc.

@ncruces
Copy link
Collaborator

ncruces commented Jul 26, 2023

WithCloseOnContextDone allows you to kill your guest asynchronously, do it easily based on a time limit, or any other signal that can be wrapped in a Context which is the standard way to do it in Go.

WithMemoryLimitPages let's you limit memory.

For IO you can use FunctionListenerFactory to "meter" WASI/host function calls, and cancel a Context if a limit is exceeded.

All of this is supported, and only tracing IO depends on experimental features.


I'm a maintainer, but not the project lead, so take the rest of this post with a grain of salt. That said…

What you're asking for is to, instead, somehow, assign a (configurable?) cost to each WASM instruction and WASI/host call, track this cost at runtime, allow you (the guest?) to query this cost, and kill the guest according to this cost instead of Context cancellation.

This is a lot of work, both design/architecture/development work (we need to decide what "cost" is, design an API to configure it, rearchitect the project to measure it, implement and test the whole thing) and a lot of runtime work (every WASM instruction, every host function call, needs to add to this cost, vs. now periodically, checking if the context is done).

The naïve implementation would be so slow you wouldn't want it, we'd need an optimising compiler (currently in development) to make it remotely palatable.

If lots of people coalesce around this being important, and on a coherent, detailed feature request, it should have legs to stand on. Drive by requests, are much less likely to get traction.

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

No branches or pull requests

9 participants