Open No3371 opened 3 years ago
Sorry that I didn't respond earlier. I like this idea a lot but it could cause problems if you restart the game when it still has updates queued. The queue would probably have to be serialized on world unload somehow. Maybe it could be saved to the world nbt data.
Oh, that's interesting, I did not expect that water processing is a long task, thought water blocks are found then updated in frame & the system is stateless.
BTW Recently I noticed WPO you referenced in Readme, the author took another approach which I think is better then counting blocks, she just check the remaining tick time out of 50 and stop processing if it's less then a configured ms value.
The reason I raised this issue is that underwater canyon or caves connected to rivers are giving me a hard time, it even make my server timeouts (tps 0) sometimes lol, apart from this I am very satisfied with Fluid Physics.
Its not a long task but if you stop processing the water update events because the tick already took too long you have to queue them or else the water just gets stuck.
What does it do now when server crash? If it does not have to save the state (and can't) when servers crash, why does slicing have to? Just trying to catch up your thought :p
I think in case of a server crash you will run into similar issues but that shouldn't happen under normal circumstances. But in my opinion a server restart should not cause such problems.
But like I said these problems could be mitigated by saving the queue to the world nbt data.
Whatever works is good enough for me as a user, and It's your mod so I believe you know what's best, It's just that I like to discuss about code design/impl with other devs so if you don't mind I'd continue this talk 😄
Now if it saves unfinished jobs every frame, if the server is totally overloaded and doesn't have spare time to process fluid in every frame (always <20 tps), will the queue grow indefinitely? Or maybe you are saying that already flowing fluid blocks needs to be serialized, but ones not yet started flowing does not have to so the jobs to be done will never increase unstoppably?
Overflow is indeed a problem. The in-memory queue would have to have an overflow catch, that just blocks the server and forces updates until the queue size is low enough (half of capacity maybe, otherwise there's the chance for constant stutter as it keeps overflowing/catching up).
If that's not too hard to do, then that could be good enough for now.
I think doing the fluid physics in its own thread is probably the ultimate solution, but I'd have to do some research on your code before making any design suggestions there. Also there's the concern that thread synchronisation costs will not make up for the performance gain of offloading physics to another thread, but if it's still possible to use shared memory off-heap in Java these days then that's actually a very appropriate implementation - since each chunk is a fixed size it might not cost that much...
256x16x16 = 65536 entries per chunk, assuming we use an int for each entry (where 0 can be air, 1 can be any solid block, and the rest are internally mapped to the different fluids, for example) then that's ~256KB per chunk in memory, so to keep even 1000 "fluid chunks" loaded in-RAM would only need to reserve 250MB of off heap memory. Is 1000 loaded chunks a lot? I don't know, honestly. If it isn't or is, the beauty of it is that fluid updates could be easily tuned to suit server performance. It wouldn't be tied to the in-game chunk load distance anymore, for example.
(EDIT: Would we even need an int array for all the different things the fluid physics sim needs? I doubt it, use a short instead - 1000 chunks loaded is now 125MB and can understand 65536 possible block values)
@cosmicdan forcing updates in these situations is a really good idea! It could also be used to fix the world unloading problem I was concerned with by just force processing the queue right before the world is unloaded.
I think the multithreading stuff would not be worthwhile because of minecrafts architecture. Since chunks are mutable one would have to copy all the necessary blocks into a separate memory region but iterating over and copying all blocks because they might be needed in a later calculation is probably more costly than just iterating over the water blocks that are affected in that moment. Well it could be optimized to sync the blocks only once and then keep them in sync via block events but that would complicate things even more. I think this would be a really great idea for an ultra-realistic water simulation where it could really make a huge difference in performance.
Indeed the multithreading aspect is more a long term thing, if at all. You're right - it may be sufficient to just implement a queue which processes as much as possible in a tick - I suppose it all comes down to how predictable and realtime you want the water to flow.
Just regarding block syncing, well - consider the cost of sending block updates between server and clients - and that's over a network. Would it really be that expensive, when parceled out correctly? Running a simulation on both client and server sides, where the server side sim is non-blocking unless a client has specifically requested a block updates, would be actually ultimate. I.e. deterministic fixed timesteps.
But yeah, maybe one day! :)
Get BlueMail for Android
On 29 May 2021, 21:38, at 21:38, Pierre Kisters @.> wrote: @. forcing updates in these situations is a really good idea!
It could also be used to fix the world unloading problem I was concerned with by just force processing the queue right before the world is unloaded.
I think the multithreading stuff would not be worthwhile because of minecrafts architecture. Since chunks are mutable one would have to copy all the necessary blocks into this separate memory region you mentioned but iterating over and copying all blocks because they might be needed in a later calculation is probably more costly than just iterating over the water blocks that are affected in that moment. Well it could be optimized to sync the blocks only once and then keep them in sync via block events but that would complicate things even more. I think this would be a really great idea for an ultra-realistic water simulation where it could really make a huge difference in performance.
-- You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub: https://github.com/LolHens/mc-fluid-physics/issues/28#issuecomment-850818662
Basically it's counting how much blocks processed and stop processing more when the threshold reached in that tick.
I'm interested to do it myself and send a PR but unfortunately the cost is too high to learn Scala which is I totally unfamiliar with 🤦