cc-tweaked / CC-Tweaked

Just another ComputerCraft fork
https://tweaked.cc
917 stars 209 forks source link

Remove the "Too long without yield" error #1623

Closed walksanatora closed 7 months ago

walksanatora commented 10 months ago

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.

fatboychummy commented 10 months ago

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.

walksanatora commented 10 months ago

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

Wojbie commented 10 months ago

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.

9551-Dev commented 10 months ago

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.

SquidDev commented 10 months ago

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:

Thoughts definitely welcome on how to address any of these!

[^1]: Mostly to do with things like slow pattern matching.

walksanatora commented 10 months ago

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)

SirEdvin commented 10 months ago

It is probably better to implement such things on java level, then on top of lua VM, that works attached to minecraft ticking cycles.

walksanatora commented 10 months ago

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)

fatboychummy commented 9 months ago

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 perform[^1] 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.

[^1]: 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.

SquidDev commented 7 months ago

Having spent more time thinking about this, I'm afraid I'm going to close this.

I think this error is pretty easy to work around when you need to, but acts as a good warning to people writing inefficient programs that they're doing something wrong.