Jump to content

How to optimize performance ? (Or the "keep the fans off" thread)


meteoritool
 Share

Recommended Posts

Hi everyone !

Remember "Macromedia Flash" ? It is a dead technology that used to allow total freedom at the expense of HUGE computation. It has been abandoned... As much as I loved the possibilities at the time, fact is, running a somewhat simple game within your browser would require all the power and memory your computer could give, no matter how powerful, and in my humble opinion, I'm happy it has been discontinued, I HATED the way my -powerful then- MacbookPro would start to spin its fans at full speed, full noise, full heat.

Now I'm a beginner in trying to master BABYLON.JS, and in my first experiments, I notice the fans of my brand new super-spec MacbookPro behave sorta the same way, soon after loading my scene, the fans start to turn fast and loud, Babylon.js pushes the computer to high temperature. And I don't want my beloved Babylon.js framework to end up like Flash !!! lol 

Checking demos on the official babylon.js site, I notice some of them render well without making the fans turn on (ex : http://www.babylonjs.com/Demos/Sponza/) but others demand too much (ex :http://www.babylonjs.com/Demos/Train/).

###So, trying to make it short, what is the good way to go in order to keep the CPU usage low ? (like in the Sponza demo)###

-Textures: -What is the recommended size ?
                 -How much CPU does it take to use bump, specular, etc... on top of the Diffuse one ?
-Lights:     -Is there dynamic lighting on an optimized scene ? Of which kind ? how many ? How to bake static lighting ?
-Programming: -Is there a way to writing javascript code that would be better than another ?
                         -example: Is calling "scene.getMeshByName("mesh.name")" more demanding than just "mesh" ?
                         -how does the "scene.registerBeforeRender()"should be handled ? 
                         -example: Is it a problem if calling "for (var i=0;i<scene.meshes.length;i++)" or "for (i=0;i<scene.textures.length;i++)" multiple times rather than just one time ?
                         -Is there a way to handle/optimize memory ?

Well this is just a few questions this topic can bring up ... I hope people participate with questions and answers, we can decipher the magic behind perfect programming together !

Link to comment
Share on other sites

Hello this is a really interesting question!

To reduce CPU usage, here are some rules to follow:

- Textures sizes do not impact CPU they are completely GPU handled

- Number of objects: try to keep it low

- Try to keep the number of materials low to avoid context switching

- In a general manner, try to reduce or completely avoid instancing new objects because it adds pressure to the garbage collector (which is fully CPU based)

- Collisions and physics are also CPU intensive

- Particles and SPS are CPU intensive

- Shaders and postprocesses almost don't use CPU

Link to comment
Share on other sites

Remember your GPU can have its own fan also :-D

I would insist on the Garbage Collector part that DK talked about because this is really the part of your code what you can deal with once the render loop is started (internal BJS is designed to not allocate new objects).

Be really careful about what objects, BJS ones or genuine JS ones (arrays, JS objects, etc) you create, sometimes without being aware of this, within the render loop. This has a huge impact on the way the browser deals with the memory allocations : sometimes the GC is triggered as soon as the objects are disposed (FF), sometimes the browser has a cache mechanism and the GC waits before starting to collect the dust to have a decent amount to sweep... but when he starts, he doesn't ask your permission (chrome). You'll feel this quickly as well in the CPU increasing charge (so the fans), as well in the decreasing FPS.

So a good advice imho, a Javascript is really well designed for this (scopes, reference passing, etc) would be to be careful and to explicitly allocate the more possible objects of your scene before the render loop starts and to work only then with this pre-allocated memory.

We've got only 16 ms to do everything... so if we could avoid to clean the house meanwhile, this may be a good option.

 

 

 

[EDIT] another option would be to have better ventilated devices :D

I'm not sarcastic, but MacBooks are known to be really densely integrated, so to warm quickly

Link to comment
Share on other sites

I just found the Tmp class at the end of that file.  That decompose should probably be using it. 

var rotationMatrix = Tmp.Matrix[0];

Matrix.FromValuesToRef(
                this.m[0] / scale.x, this.m[1] / scale.x, this.m[2] / scale.x, 0,
                this.m[4] / scale.y, this.m[5] / scale.y, this.m[6] / scale.y, 0,
                this.m[8] / scale.z, this.m[9] / scale.z, this.m[10] / scale.z, 0,
                0, 0, 0, 1, tmpMat);

Quaternion.FromRotationMatrixToRef(rotationMatrix, rotation);

An object pool class would be safer though.  It looks like it would be easy to inadvertently write to the same object from different sections of code.

Link to comment
Share on other sites

yep, this is a good idea

The Tmp (secret) class is quite new (so not that refactored everywhere in the legacy code) and intended to share pre-allocated objects (so memory) instead of allocating temporary ones within the other class methods. It's not intended to store persistent values, just to re-use the memory and thus to keep the GC as quiet as possible.

For now, AFAIK, the code was refactored using the Tmp class mostly in the methods usually called, or supposed to be called, in the render loop or generating too many temporary object allocations (world matrix computation, SPS, parametric shape morphings). It could of course be used more widely, just a matter a time to refactor everything.

This remains an internal mechanism to optimize the framework and is not really a end-user tool.

 

 

Link to comment
Share on other sites

15 hours ago, jerome said:

It could of course be used more widely, just a matter a time to refactor everything.

This would make me nervous.  It would be easy to call a function that is using the same Tmp variable you are using.  I would feel more comfortable using something like:

var tmpMat = Tmp.get(BABYLON.Matrix);  //get function would make sure you are the only one using it

//do whatever you want here

Tmp.recycle(tmpMat);  //return it to Tmp so that it can be safely used again.

Just my 2 cents.

Link to comment
Share on other sites

Hey people !

I see we have different points of view and approaches, but it's still a major topic for everyone, as soon as you discover a new creative tool, you quickly reach the limit and have to deal with "the way how to" , self-teaching takes some time but is rewarding ! Having a good teacher though, make things much more efficient and fast, thanks for your answers ! I hope I can become as expert as you are ;)

I'm only trying to get the right coding method before going too far ahead. I have, thanks to the wonderful debug layer, realized that FPS is BIG TIME impacted by shadows !!!
PointLight and shadowMap at 1024 is a NO GO !!! If I disable the Shadow, my scene hits 200PotentialFPS quite often, when I enable it, goes down to 50FPS.
Usually, I try to make something that can run on an iPad2/3, it is my "standard". But its too limited so I also make more demanding scenes. The MacbookPro Retina full specd is amazingly fast and silent ! It is ME that is to blame, not the computer ;-) 

@Deltakosh @jerome I have only "heard of" garbage collection ... I think I get what it is about more or less ... I'm willing to use the BABYLON.JS framework with its multimedia properties, MP3 sounds, WEBM videos, lots of meshes got from .babylon files. They are often big sized and not necessary at startup. Do you mean that MP3 or WEBM files or assets, should all be loaded and created before runRenderLoop ??? Its not as if I was trying to make a MMORPG, but I thought it would somehow be possible with BJS >_<

 

 

Link to comment
Share on other sites

The fans usually run because of the gpu, not the cpu (of course this is a very generalized statement). Unless you run very heavy computations every frame, I doubt the cpu is the reason for that.

Gpu gets hot. On your computer, on your smartphone. Think about the amount of computations required to render one frame, and multiply it times 60 per second. It's working hard... Let the fans run, they only do their job ☺

Of course optimizing the computations will help. Using simpler shaders will help. But there is usually no way to avoid gpu heating when rendering a 3D scene.

 

Link to comment
Share on other sites

Fan speed is only avoidable with either a water cooled tower or fan-less tablet.  Shifting noise from the cpu fan to the gpu fan is a zero sum game.

The gpu fan noise usually comes with better results though.  Amdahl's law dictates that the % of time spent in single threading drastically limits throughput.  Suggest you try to limit the overhead of cpu during render loop.  See you discovered the debug layer, so you should be able to measure the effects of these tips:

  • indicate freezeWorldMatrix on all meshes, which are background & never move.
  • indicate checkOnlyOnce on materials.  If it does not screw up everything, keep it that way.
  • merge meshes of the same material, as long as you are not running animations or setting other properties independently  on them.
Link to comment
Share on other sites

lol The fans getting on at very fast pace is just a sign that something very intensive is going on, a basic scene shouldn't be something intensive for my computer, but it's my mistake of course. This is not really a topic about cooling system issues though... It's just that some scenes tend to be better than others, and looking at the Sponza Demo, I'm looking for ways to achieve something THAT optimized (thus doesn't turn the fans of the PC on)... Just to give you an example : it is acceptable that the fans starts to run at fast pace when I export a .babylon file from a complex Blender scene, the task can take some time and it computes the stuff at full speed, okay, but I can't accept the same kind of "heating" when my scene is rendered realtime, it kinds of ruins the experience IMHO. This this achievable, I'm sure ;). I'm trying to get as much info I can. I already use LevelOfDetail, and other stuff from the tutorials. They are great by the way.

1 hour ago, JCPalmer said:

these tips:

  • indicate freezeWorldMatrix on all meshes, which are background & never move.
  • indicate checkOnlyOnce on materials.  If it does not screw up everything, keep it that way.
  • merge meshes of the same material, as long as you are not running animations or setting other properties independently  on them.

Thx for the tips, I'll review and check the difference it makes ;-)

Speaking of CPU, I personally englobe CPU and GPU in the term "CPU", as few people have proper dedicated one, to mention the overall computations. It's because I come from the audio world, where CPU is the gauge ^_^ My mistake.

Link to comment
Share on other sites

1 hour ago, Vousk-prod. said:

For the checkOnlyOnce flag on material, we have markDirty() to notify a change for one render loop, is there a similar method for mesh with freezeWorldMatrix ? That could be super usefull.

Have not looked at that code recently, but one of these should work:

  1. Call freezeWorldMatrix() again.  It calls computeWorldMatrix() one last time to ensure it was called at least once.
  2. Call computeWorldMatrix(true).  The force parameter should "force it" without changing the frozen state.
Link to comment
Share on other sites

On 28/03/2016 at 2:59 PM, jerome said:

That's right. Thanks.

On 28/03/2016 at 4:16 PM, JCPalmer said:

Have not looked at that code recently, but one of these should work:

  1. Call freezeWorldMatrix() again.  It calls computeWorldMatrix() one last time to ensure it was called at least once.
  2. Call computeWorldMatrix(true).  The force parameter should "force it" without changing the frozen state.

Solution 1 works perfectly. Thanks.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...