CPU Optimizations for animated meshes

Ok, just for the sake of testing, can you try to add this:

BABYLON.Scene.prototype._internalPick = function() {
    return new BABYLON.PickingInfo();

This way we will be sure nothing related to picking will be executed.

Hmmm… doesn’t seem to effect it…

So it seems the picking is not the problem…

Have you tried to profile in Chrome what happens when there’s the problem?


evaluateactivemeshes can be completely wiped out by calling scene.freezeActiveMeshes()

that’s worth a try

1 Like

The graphical parts of your game can primarily impact on two systems of the computer: the GPU and the CPU. The first rule of any optimization is to find where the performance problem is, because strategies for optimizing for GPU vs. CPU are quite different (and can even be opposite - for example, it’s quite common to make the GPU do more work while optimizing for CPU, and vice versa).

Common bottlenecks and ways to check for them:

  • GPU is often limited by fillrate or memory bandwidth.
    • Lower the display resolution and run the game. If a lower display resolution makes the game run faster, you may be limited by fillrate on the GPU.
  • CPU is often limited by the number of batches that need to be rendered.
    • Check “batches” in the Rendering Statistics window. The more batches are being rendered, the higher the cost to the CPU.

Less-common bottlenecks:

  • The GPU has too many vertices to process. The number of vertices that is acceptable to ensure good performance depends on the GPU and the complexity of vertex shaders
    . Generally speaking, aim for no more than 100,000 vertices on mobile. A PC manages well even with several million vertices, but it is still good practice to keep this number as low as possible through optimization.
  • The CPU has too many vertices to process. This could be in skinned meshes, cloth simulation, particles, or other game objects and meshes. As above, it is generally good practice to keep this number as low as possible without compromising game quality. See the section on CPU optimization below for guidance on how to do this.
1 Like

Thank you for the detailed response. I have a decent understanding of the underlying principals, I just don’t know the best way to apply them in Babylon. Your links are Unity specific, so they aren’t very useful for this example, although it’s looking more and more like converting to Unity will be my best bet.

Anyways, just wanted to bump this thread in case anyone has any idea what could be causing this. Still having the same issues. I did try reverting my local repo back to 6 months ago when this problem didn’t exist (and the old single mesh player model was in the game), and the lag is occurring. This proves that the player model isn’t causing the lag, and is leading me to believe that it could be a Chrome issue, but I also have no way of proving that.

Problem still occurs :face_with_head_bandage:

This is almost impossible to help you without a solid repro in the pg that we can profile. Or even a repro on your game with a reference to babylon.max.js

Something we can see and not just imagine :frowning:

Do you not have a CPU spike in the PGs that I posted previously?

And I’m not sure what you mean by: “Or even a repro on your game with a reference to babylon.max.js” Are you saying to add babylon.max.js as an import so you can diagnose it? Would it not be possible to do that via console?

Here’s a video that shows the problem as clearly as I can show it:

Well I cannot debug a video :smiley: And no I see no spike in your PG unfortunately

Okay, so what do you need from me?

a repro :slight_smile: some code running somewhere but using babylon.max.js instead of babylon.js (or a non minified version of the code) so I can debug

I scraped this off the video.

yes but this is pure minified code unfortunately. Plus you need to spend 20mins before reproducing the issue

The current JS file can be pretty printed, it isn’t uglified at all.

And I can add Babylon.max.js give me a minute.

Also please make sure to share a way to repro easily (Help us helping you)

Okay so I’ve added babylon.max.js, and you can pretty print the app.min.js code in the dev console to see the entire client code.

To reproduce the bug, go to an area of the map where a player’s base exists (hold ‘g’ to see the map, the red squares are claimed zones where bases are) Here’s a screenshot of where a big base exists currently:

If you walk forward (w key), and move the mouse around while pointer locked, you should feel the lag. Some users don’t feel it right away. If you want to feel it more, go into settings and enable shadows.

Let me know if you need anything else

As an experiment, what if you tried disabling all event listeners from Babylon on pointermove, and then re-added just the one you use for picking (without going through Babylon but engine.getRenderingCanvas().addEventListener(“pointermove”))

If I remember, it would be something like:
for (let camera of scene.activeCameras) {
camera.detachControl(true, true, true)

And in your pointermove event, don’t do anything other than copy the mouse coordinates

Then, on the next tick / render or checkInputs, check if they changed or pick and handle accordingly

I’m typing on phone so it’s harder to verify those method names are correct. You can verify in devtools there’s only one event listener bound to the pointermove event on the canvas element

Also I would try using MeshOptimizer to merge & compress your meshes — GitHub - zeux/meshoptimizer: Mesh optimization library that makes meshes smaller and faster to render. It’s probably harder to pick 30 meshes than one. And maybe also try wrapping your meshes in the BoundingBox gizmo thing that lives somewhere in the docs.

But 30%ish CPU time spent on evaluateActiveMeshes is consistent with what I see in the game I’m building. I’m using an Octree and the scene has around 600 meshes in it, but usually up to 150 pass the frustum & Octree checks. A big part of it is pushing onto the array of active meshes, which makes me wonder if it’d be faster for evaluateActiveMeshes to be based on a generator rather than a SmartArray. Then selecting the active mesh would just look at the blocks entries insted of concatenation, and you could de dupe by looking at the renderId on the mesh I think