Very High CPU Usage
Ithronyar opened this issue · 16 comments
Pretty self-explanatory. When the X-ray feature is toggled on, the game spikes up to 95-100% CPU usage and stays there, even at the lowest distance (8). CPU usage remains high when paused, standing, flying, and walking. Just tabbing out to write this made my PC hang, and I had to go back and toggle X-ray off.
When X-ray is off, CPU usage goes back to normal. Everything has been tested in a new game installation, with everything at their defaults and only this mod enabled. Same results.
Relevant (and possibly relevant) specs:
CPU: Dual-Core Intel Pentium G2030
GPU: AMD Radeon HD 6670
MC version: 1.12.2
Forge version: 14.23.1.2555
Mod version: 1.4.0
Java version: 1.8.0_25 64-bit
Java allocated memory: Default (1GB)
Hmm, thats very odd that that's happening. I could only assume that either your system specs are to low to run a mod doing something like mine is.
( I have to loop through every block every tick and create a render around them every tick. I also then have to check every block to see if it's in the long list of blocks that the user has added. It's quite a heavy process and it's the reason why it's got a toggle off. )
Hmm, It's also likely that it's not that. What is your CPU like when normally running the game? what sort of %? I have done my best to try and make the mod as tiny of an impact that I could but it's doing a heavy task :P I might slow it down to every other tick or something like that.
Normally, the game runs at an average of 35% CPU usage. Usually it takes a lot of unoptimized/tick-heavy mods to start incrementing that number to 100%. This mod does it single-handedly.
And I'm not surprised, if the mod works by looping through all blocks on every tick. That's probably the most inefficient way I could imagine a mod like this to work.
It would function exactly the same if it only updated every 20/40/whatever ticks. It could even loop every 5000 ticks, and the update lag STILL wouldn't be visible 99.9% of the time, because usually worlds have static ores that were created on generation, with none being placed/moved afterward.
I like your thinking, although finding them and storing them in something would still be a pretty needy process and would only be able to be done per x amount of chunks. It would simplifiy the rendering task though. Logically I could store the blocks in json to reduce the amount of regulated searching but that would just end up making huge files of blocks you are likely to never go near again :P I am working on a way to stager the search so it does a pulse affect by scaning a block every tick instead of all blocks every tick and then showing you the render as it finds that one block per tick. Segmentation is the best way I've found to reduce the load but getting it to work is showing be quite the bitch.
Surely the X-rayed blocks can be stored in RAM. I'm guessing all that's needed to store an X-rayed block is the location and maybe wireframe RGB values; the latter can be condensed down into a byte or less, while the others are just 3 integers. Even for a chunk literally filled with ore, that would only be about 3mB of RAM, if those variables are unsigned.
You have to remember about the games that last for 9+ hours exploring maps and new chunks. All that ram starts to fill up pretty quick.
So... unload X-ray data that hasn't been used for a while, and/or have a memory cap and delete the oldest entries once that cap is hit. If the player passes through that area again, it can just be rescanned and added back to the block/chunk array.
Hmm, I like your idea. I'm going to have to look into it and see what I can come up with :P You seem to know what you're doing... You should give me a hand haha. ( Java isn't my main language by any means. )
I'm tempted to help, actually... But I'm a noob programmer at best, and I've had horrendous experiences with Java and Minecraft modding. I might try something eventually, but don't hold your breath. ;)
Haha, I've had the same experiences. It all clicks eventually and shit starts to make sense. This repo is pretty simple and follows forges current specs for what a MC Mod should look like and function like. I've commented it pretty well too haha. Might be a good idea to try with this one. I hightly suggest using intelij over the other one :D GL if you do help out.
@Ithronyar So I've been looking into a lot of different way's of trying to mitigate this issue. After doing some simple math, on the smallest radius the mod is scanning around 500k blocks every tick. This is why the mod is causing such a high amount of lag on the server.
To fix this I have attempted a few different methods scanning, loading and saving. Currently the best way I have found of mitigating the issue is to put a minor delay in the speed that my finder thread
is able to look for the blocks and display them.
This is what that looks like, ( small loop, the purple is debugger showing where the finder is currently looking. )
https://i.gyazo.com/bd163259a9c0f934b878867b4fda7592.mp4
Basically, trying to scan 500k blocks with a 1 millisecond delay is enough to slow the finding of blocks down by so much that it's almost useless to even have the mod turned on. I've had a few more idea's since I last worked on this but for now I am going to have to outsource the help to see if I can get someone else's opinion on what might be the right path to take.
How does this sound to you? If you where to have a minor momentary high CPU usage for the mod to scan a few chucks around almost instantly and then dye back down and use a smarter system to store the found blocks and to then only try and re-find blocks in new, unseen, chucks. This would mean you would lag for a few seconds maybe on first startup in a new area but after that first delay the mod would start to scan in a way that wouldn't require such a large task to have happened. I could make it scan the first few chucks slowly but this would cause you to not see any blocks for around 20 seconds after turning the mod on. I think thats too much but having a bit of lag and then smooth running is better than having a lot of lag all the time for slower systems.
A quick full-CPU scan followed by a slower block updating tick is the most efficient way that I can imagine this mod working. The only other improvements I can think of besides that are:
- Somehow optimizing the block-searching algorithm (probably not easy)
- Caching the results every few minutes for quicker loading (maybe; could cause save bloat)
- Somehow running the more repetitive looping on the GPU (maybe; might just kill framerates)
Even with no further improvements, a few seconds of lag and then smoothness is orders of magnitude better than constant super-lag forever.
Yeah, my research found the same thing. It's all down to my thread running to find and load the blocks. My current idea is to store the found blocks on memory by chunk, if that chunk isn't used again for X amount of time it will remove the saved blocks from memory. This means super quick loading and a hell of a lot less lag.
Another idea: If there's a way for the mod to listen for chunk edit events, then it can track the chunks it's already scanned, and ignore scanned chunks that haven't been updated. Then the mod would have little or no CPU load once it scanned all the loaded chunks. Combined with caching, it would only ever start a scanning cycle when a new chunk is generated, and when a chunk has been modified.
As of now I've temp fixed the issue by slowing the thread down. All chunk saving methods just became memory issues.
Yay, More improvements needed thats for sure but for now it's small but noticable improvement