-
Notifications
You must be signed in to change notification settings - Fork 290
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
Allow resumable calls to recover after running out of fuel #696
Comments
Being able to use the fuel system together with Also, if this feature is not possible for technical reasons, would it still be possible to let wasmi insert a function call to an imported function every n instructions? This way, we could at least have a system to yield from execution. This could help with using wasmi in an async context. |
@tomaka Thanks for writing the issue! I have a few questions ...
To answer some questions: At the moment fuel is somewhat arbitrary. However, there are plans to adjust our fuel costs to a similar policy as to what Wasmtime does in where basically one instruction roughly costs 1 fuel to execute. Currently we are trying to do a more precise job but since this can only be a heuristic at best it is better to make this even simpler just like Wasmtime did. @Lucky4Luuk I think it should be technically feasible to implement this feature. The only actual question is if it is possible to implement this feature without massive performance regressions. We have been dealing with lots of those performance regressions for various reasons lately. Still trying to figure out why. At the moment most of the currently open PRs cannot be merged due to weird performance regressions. For the same reason we probably won't implement a feature to call a host function every X instructions. First this is heavily underspecified and secondly host function calls are among the most expensive things you can do in |
Well, in smoldot I also need the parameters that were passed to the host function. Again, the idea is simply to implement the body of the host function "externally" (which makes it possible for example to perform asynchronous operations) and not within a callback.
That's your choice. I suppose that every error that can be resumed from could lead to
Note that this is not really related to my explanation. "One instruction == one fuel" is just as arbitrary, because I assume that nobody is going to calculate the amount of fuel to pass to |
Technically you could embed those parameters into the host error that caused the interruption of the resumable call, right?
That's partially what already happens in the I will think about a possible API to extend resumable calls with |
@tomaka How pressing is fixing this issue for smoldot? |
It's not pressing. The objective is simply for smoldot to be able to resist to malicious chain. At the moment, if you connect smoldot to a malicious chain, this chain can freeze smoldot. |
Okay thanks a lot for this info! |
Hello. Not to necro this thread but I have a viable use case for this in my operating system AbleOS. I'd like to have this functionality. |
This is currently blocked mostly because of two things:
|
The goal: I'd like for the wasm engine to be pauseable so I may do task switching. I have two main ways that I think my goal could be accomplished. I think there are two ways this can be done:
And if both are implemented I think there is enough variation that all use cases can be covered. My usecase would require a pause button that halts the engine at the next instruction, stores state and can later be unpaused. Thank you for the quick response! |
As we all know, because of the halting problem, it isn't possible to know whether the execution of a Wasm function will finish in a finite time.
While a Wasm function is being executed, maybe everything is okay and it is simply taking a long time, or maybe the Wasm execution is stuck in an infinite loop. It isn't possible to know in which of the two scenario we currently are.
Because the program that is interpreting the Wasm doesn't want, itself, to be stuck infinitely, it needs some sort of protection against the Wasm being stuck in an infinite loop.
While the program interpreting the Wasm can't know whether the Wasm is stuck in an infinite loop, it can use heuristics.
For example, if the Wasm has been executing for 10 seconds while normally it should take around 2ms, then it is likely to be stuck.
Wasmi provides a fuel system, making it possible to interrupt the execution of the Wasm after a certain number of instructions have been executed.
This system is however not very flexible. It's all-or-nothing: when all the fuel has been consumed, the execution completely stops and can never be resumed.
Furthermore, it is difficult to map "fuel quantities" with real world time/CPU usage. A precise fuel number means that whether the execution will run out of fuel or not doesn't depend on the speed of the machine, which has the advantage to be deterministic. However, this is also a drawback: it is not possible to stop the execution after an approximate number of seconds. If you pick a certain fuel quantity, on some platforms this fuel will expire quickly and on some others it will expire very slowly. Fuel quantities are very arbitrary anyway, and I think that it is legitimate to want to stop after a certain number of real life seconds.
In order to solve that problem, I would suggest to make it possible to combine the
call_resumable
feature with the fuel system.When the fuel expires,
call_resumable
should return aOk(ResumableCall::Resumable)
(or something similar) instead of anErr
.This would make it possible for the API user to choose what to do: either stop the execution, or add more fuel and resume the execution. This provides maximum flexibility to this feature.
The API user could do things such as print a warning after a certain time, ask the human whether to continue or not, de-prioritize the thread executing the Wasm after a certain time, etc.
The text was updated successfully, but these errors were encountered: