Dynamic Surroundings

Dynamic Surroundings

51M Downloads

DynamicSurroundings: Some simple step, consuming Vast amout of CPU time.

jahtim opened this issue · 10 comments

commented

Mod Version:
1.0.6.2
Forge Version:
1614(1.7.10)

Description:
I wrote a small threaded monitor mod to sample from client thread. It can indicates which function takes the most time of cpu and causing lag. And my result is amazing: the following function takes the most time(3% of total CPU time) in a large modpack among the modded functions:

org.blockartistry.mod.DynSurround.client.RenderWeather-renderRainSnow -> org.blockartistry.mod.DynSurround.client.storm.StormRenderer-render -> org.blockartistry.mod.DynSurround.util.random.XorShiftRandom-nextGaussian -> org.blockartistry.mod.DynSurround.util.random.XorShiftRandom-genGaussian -> java.lang.StrictMath-log=31813,

(This is the second modded function btw. 2% of CPU time) cpw.mods.fml.common.eventhandler.ASMEventHandler_1959_AMEventHandler_onEntityLiving_LivingUpdateEvent-invoke -> am2.AMEventHandler-onEntityLiving -> am2.buffs.BuffStatModifiers-applyStatModifiersBasedOnBuffs -> am2.buffs.BuffStatModifiers-applyOrRemoveModifiersForBuff -> am2.buffs.BuffStatModifiers-clearAllModifiers=19460,

(this is rank of all functions, 1st(25%), 2nd(17%), 3rd(7%), the first 10 is all vanilla function call)
net.minecraft.client.renderer.texture.TextureAtlasSprite-func_94219_l -> net.minecraft.client.renderer.texture.TextureUtil-func_147955_a -> net.minecraft.client.renderer.texture.TextureUtil-func_147947_a -> org.lwjgl.opengl.GL11-glTexSubImage2D -> org.lwjgl.opengl.GL11-nglTexSubImage2D=496444,

org.lwjgl.opengl.Display-swapBuffers -> org.lwjgl.opengl.DrawableGL-swapBuffers -> org.lwjgl.opengl.ContextGL-swapBuffers -> org.lwjgl.opengl.WindowsContextImplementation-swapBuffers -> org.lwjgl.opengl.WindowsContextImplementation-nSwapBuffers=341152,

net.minecraft.client.renderer.texture.TextureUtil-func_147955_a -> net.minecraft.client.renderer.texture.TextureUtil-func_147947_a -> net.minecraft.client.renderer.texture.TextureUtil-func_147954_b -> org.lwjgl.opengl.GL11-glTexParameteri -> org.lwjgl.opengl.GL11-nglTexParameteri=147966,

So, if it is possible, would you mind do some performance optimization in here:
org.blockartistry.mod.DynSurround.util.random.XorShiftRandom-nextGaussian -> org.blockartistry.mod.DynSurround.util.random.XorShiftRandom-genGaussian -> java.lang.StrictMath-log=31813,
Fastmath could be a solve, and archetecture of code might influence performance as well.

commented

Move this part to another thread is also a best solution.

commented

Did you run a Java profiler as well to benchmark your results?

commented

Actually i use mcprofiler at first, but at some point it shows some unspecified operation which is taking a lot CPU time

commented

Do you know the number of times that method is called over the time interval? Yes, it is a leading question. :)

commented

well that is hard to find.. I can only find what function is in CPU action. I try to make a guess
nSwapBuffers run 20 times a second. and I run for 20min. the action count of nSwapBuffers is 341152 in all. I can run log for 10 millions of times in a second. So i guess the time of method call of log is 10^6 times in a second

commented

I do most of my profiling with DS versions 1.10.x+. I use Netbeans to do the profiling of Minecraft/Dynamic Surroundings. What I usually see is a tremendous amount of time spent in the rendering code. That makes sense because, well, its a video game.

The code related to genGaussian you mention above is for generating random values for handling rain rendering as well as rain particle effect rendering due to rain. This method is also used by a bunch of other particle code for generating random values for particle velocities and the like. In other words, it is called a lot. So depending on what is going on in your world it could take up a percentage. (The XorShiftRandom code/behavior is identical between the 1.10.x+ versions and 1.0.6.2).

I have not found a "fast math" equivalent for genGaussian. The generation of that random value is mathematically tricky. I did for the integer randoms, and that is why XorShiftRandom came to be.

commented

Maybe you could try an aproximate log() ? for example:(5 times faster than Math.log())
public static double log(double x) {
return 6* (x - 1) / (x + 1+ 4* (Math.sqrt(x)));
}
when x < 0.03 the difference between log() and Math.log() is more than 3% ,when x grows larger, log() becomes more acurate.

There is another solution: use volatile double, an object lock(or a ConcurrentLinkedQueue) and another thread to generate (a queue of) gaussian.

commented

I think what this may be, as well, is the dust particle effect. For 1.10.x I disabled the effect on non-dirt blocks because of the overhead, not to mention folks used smooth stone for building. When I get to looking at 1.7.10 DS I will see about backporting these changes as well as reviewing RNG efficiency.

commented

🙋Diamonds to you, Cruncher. Appreciate is always.

commented

Pushed v1.0.6.3 to CurseForge.