Remove the "Too long without yield" error
walksanatora opened this issue · 10 comments
Useful information to include:
add a game config called disableYieldCrash
what this does it makes it so instead of throwing too long without yielding
it just pauses the Computer untill it gets continued again (so you dont have to manually yield your VM and can let the do it as needed). mabey along side this we could also get a "yield timeout" config if it does not exist
why: would allow me to have less yields and wont punish me if I forget them.
CC: Tweaked is very much focused on event-driven programming. If you're running into issues with yielding, your programming (or whichever addon mod you're programming for) is doing something wrong. There are very rarely cases where you should actually be doing heavy polling, especially since most systems in Minecraft only update once per tick.
This would incentivize people to not yield, and people would very quickly run into performance issues as multiple computers just while true do
loop forever into the abyss.
if not a global for every compter
mabey a way to "grant" this power to a specific computer eg: a command computer or trusted users computers
but I mean I could just have a while true loop with time polling and it can still loop forever into the abyss... so it allready could be a issue if someone wanted to make it one
Could you show example of code you are writing that has this issue? I am sure we could figure a way to rewrite it to yield properly.
IMO forcing yields is essential as not using any yields would break apis such as parallel.
Having yields makes sure that you can reliable "multitask" pretty much any piece of code there is
Also i dont really see the point in not yielding. If you just need the extra speed yield once every second or something. It really is not that much effort.
I have sort of thinking about this ever since #119 was merged. As computers can be pre-emptively interrupted there's not many places where we still need "Too long without yielding"1. There's definitely places where this would be useful, when doing large complex computations.
However, I'd definitely want to make this change universally, rather than making it a config option (either globally or per-computer). Adding configs for these sorts of things make the code significantly more complex, so something I'd want to avoid.
However, there are definitely some issues I've not got a good solution for:
-
There still needs to be a way to manually terminate a program. Currently we do that by queueing a
terminate
event, but if someone isn't yielding that's obviously no good.We could just fire an asynchronous error (much like we do now for "Too long without yielding"), however that's not great for things like door locks which want to ignore terminate events.
You'd probably need some hybrid system which queues a
terminate
event initially, and then upgrades it to an asynchronous exception if the computer doesn't yield within a few seconds, but that feels pretty clunky to me. Not quite sure what the best option is. -
As fatboychummy touches on, I am a little wary about encouraging inefficient programming styles. One of the most common times people hit the error is when busy-waiting for something (e.g. a redstone change) rather than using some appropriate event.
It's tricky - there's definitely valid use cases for it - but also a lot of ways to misuse it.
Thoughts definitely welcome on how to address any of these!
Footnotes
-
Mostly to do with things like slow pattern matching. ↩
It is probably better to implement such things on java level, then on top of lua VM, that works attached to minecraft ticking cycles.
Could you show example of code you are writing that has this issue? I am sure we could figure a way to rewrite it to yield properly.
what i was thinking in the context of say a WASM vm (or other architecture sim) where I want to squeeze as many cycles as I can out of the computer before yielding. because yielding every instruction would tank performance and then it becoms a fine tuning game of "when do we cut off" and also determining "how long can this instruction take" and not to mention the ever present times where the game just lag and the computers decide to crash (happened fairly often when I was working on a addon and was inspecting debugger causing my lua program to have to crash and startover)
no it is mainly cause when it checks for "too long without yielding" I think it checks time since last yield
which in the case of eg: debugger pausing the entire jvm causes a high likelyhood of it crashing (hence I believe I should propose in another thread that the TooLongWithoutYielding be converted to tick-based instead of second based)
unless you talking about the "silent yield" idea then yeah probally should be implemented java-side (although mabey modifications will be needed to cobalt)
I think it checks time since last yield
I would assume it checks time since it started running that specific computer, not since the last yield. If it were the case that it checked time since last yield, any computer that takes too long would cause all other computers that were waiting for that computer to yield to also get the error. A cascading Too long without yielding
.
but I mean I could just have a while true loop with time polling and it can still loop forever into the abyss... so it allready could be a issue if someone wanted to make it one
Sure, but it requires a bit more knowledge to perform1 than just a straight-up while loop. If this were implemented, any new player could just write like 30 while true do loops without thinking anything is wrong... And boom, their little laptop is lagging like crazy.
I honestly think the downsides outweigh the upsides on this. There's only a few (very rare) usecases for it, but a lot of ways to misuse it accidentally. I can see maybe doing this for creative servers (though I would still disable it on any of my creative servers! That's performance I don't want wasted.), but is this needed at all in survival? Not really.
Footnotes
-
The simple
os.queueEvent("quick") os.pullEvent("quick")
at the end of each loop comes to mind as one that is easy enough for new players to do (if recommended by someone else), but that will at least give other computers time to run in between each yield. Actually polling for the time to check if you need to yield, however, is much more advanced and not something I've really seen many people do, especially those new to CC/Lua. ↩