Recommended optimization for pointer movement

I noticed in my project that my framerate would dip significantly as I whipped the mouse around the canvas. I would see as much as a 20 fps drop. My scenes aren’t massively complex. It’s a “zone” in an MMORPG with simplistic art (early 2000’s era recreation).

Anyway, I started digging into the default pointermove observers and the event handlers and made a few changes to my local JS file and want to share my feedback.

#1) I stopped doing ray-picking on mousemove. Yes, this technically breaks the “what mesh is under my cursor” mechanics but I don’t need that. If I want to know, I can do a manual pick. I am not aware of a cleaner / built-in way to do this. If one exists, please let me know lol.

#2) I noticed that between each call to the main render function, _onPointerMove could be getting triggered multiple times (ie. high-performance mice that are polling at very high rates). It seemed to me that processing _onPointerMove 5-6 times between any observable change on-screen is pointless. So, I added a check inside _onPointerMove that checks a simple true/false, if true, do a full pointer process cycle and then set the flag false. If false, bail. Then in my main render function, I set the flag to true. This ensures I only ever process _onPointerMove once per frame render.

I still see framerate drops, but not as pronounced. Even if I completely erase the event listeners using the dev console, I still see framerates drop as the mouse moves around. This may just be expensive native mouse processing by the window.

Hey there,

I was wondering, why were you doing ray-picking on mouse move? Have you checked the action manager class? That’s what I have been using and I have not seen any frame rate drop on mouse move. Use Actions - Babylon.js Documentation . Hopefully this will help.

That’s the thing. I’m not! BJS is! My modifications are the window.mm section and the // commented out pickResult at the bottom. I drop the scene.pick and pass a null so future code works.

Here is the native code:

this._onPointerMove = function (evt) {
    if (window.mm>0) {
        //console.log("skip");
        return;
    }

    window.mm++;

    _this._updatePointerPosition(evt);
    // PreObservable support
    if (_this._checkPrePointerObservable(null, evt, evt.type === _this._wheelEventName ? _Events_pointerEvents__WEBPACK_IMPORTED_MODULE_0__["PointerEventTypes"].POINTERWHEEL : _Events_pointerEvents__WEBPACK_IMPORTED_MODULE_0__["PointerEventTypes"].POINTERMOVE)) {
        return;
    }
    if (!scene.cameraToUseForPointers && !scene.activeCamera) {
        return;
    }
    if (!scene.pointerMovePredicate) {
        scene.pointerMovePredicate = function (mesh) { return (mesh.isPickable && mesh.isVisible && mesh.isReady() && mesh.isEnabled() && (mesh.enablePointerMoveEvents || scene.constantlyUpdateMeshUnderPointer || (mesh._getActionManagerForTrigger() != null)) && (!scene.cameraToUseForPointers || (scene.cameraToUseForPointers.layerMask & mesh.layerMask) !== 0)); };
    }
    // Meshes
    // var pickResult = scene.pick(_this._unTranslatedPointerX, _this._unTranslatedPointerY, scene.pointerMovePredicate, false, scene.cameraToUseForPointers);
    _this._processPointerMove(null, evt);

};

I just checked with the project I am currently working on. That is not a small project, I moved the mouse as fast as I could but I saw no frame drop. My graphic card is of 2013 so nothing special really. Are you sure you do not have some picking done some other place in your code? Also, are you aligned with the latest version of BJS? I am afraid I can not help much with this, have you tried reproducing in the playground?

I noticed something similar a while back.

1 Like

I will do some more digging to see if I can see what else might be capturing pointer moves. The framerate drops I notice are at extreme rates (120 fps will drop down to around 100fps). I’m on a GTX980. Granted 120 to 100 is not going to be noticeable, but I’m trying to squeeze every last drop of performance out of BJS.

I’m afraid you might just be wasting time. If you are at the optimization stage and notice issues, you should look to the profiler to identify bottlenecks.

The profiler is infuriating sometimes. It will just give me generic entries like “Task” and “Function call” but not actually tell me any more detail than that. On top of that, any operation that takes an extremely short amount of time, regardless of how many times it’s repeated, and potentially adding up, gets dropped from the timeline.

I spent a few hours yesterday investigating this some more and, in BJS’s defense, I think I may be giving scene.pick a bad rap. My UI consists of a home-built “window” system which are just floating / position:absolute divs. The fewer I have on the screen the less noticeable the mouse-movement framerate drop is. One window in particular seems responsible for about 50% of the drag. The base class of the window is not complex, nor is the final class - and neither hook into any mouse movement handlers. It’s very perplexing to me, and I’ve been a web developer for a long time. I haven’t given up yet, though.

Hey there, I am glad you were able to understand the issue. As I have never used BJS with overlaying HTML divs I have never experienced this, probably this is related to how BJS behaves with HTML. Unfortunately the BJS team is not around until the beginning of January so you will have to cope with it for now.

A repro would be amazing so we could look into the profiler to better understand the root cause of the issue. Would it be possible to share one ?

If I can figure out the external assets stuff, I’ll try to get something built. For now, don’t sweat this too much as I think the drag on FPS is more about the DOM stealing compute cycles, and not specifically BJS doing extraneous work.

I fully intend to get to the bottom of this since my game makes extensive use of HTML for its GUI, and until I find/fix the root cause, the problem will continue to stifle my framerates.

Thanks

I would definitely prefer it being related to the dom :slight_smile: