Poor JS / jQuery performance, especially in IE9 and Firefox

I am having serious image and performance issues with the script below. The biggest problem is that the animation of the object becomes really jerky, almost crippling, so in IE9, but more and more annoying in Firefox.

Until recently, it was pretty fast, but I'm worried that complexity is slowing down. Oddly enough, the Sunspider Test runs faster on my IE9 instance than on Firefox.

script (which is a fragment of a large collection ***):

  • Checks the HTML5 session storage log for users through the game.
  • Depending on the stage, an object is animated between the two using crSpline .
  • Ensures that the browser window follows the object through a large canvas, through scrollLeft, etc.
  • Finally, it loads the popup through the colorbox .
  • When this window is closed, the user's progression log is increased accordingly, and the object moves again.

Are there any obvious speed improvements that I could make to my code? There is a fair battle, how can I reduce this? Are there any infinite loops that I skip? Is there any software that I can use to profile JS slow points?

*** (I cannot provide other JS files or HTML, but I have identified this script as a problem)


UPDATE: After more honest testing, it seems that the step animation function that follows the object in the window through scrollLeft causes jerky animation. Removing it greatly improves the situation.

However, this is not a viable long-term solution. A quick solution is to call the follow function after completion, but it is a much less pleasant experience for the end user, especially when the object moves long distances.

So, how could I change the step function to run "slower" / more efficiently? . I assume that jerky is caused by him, using all available resources to track the object every millisecond.

(function ($) { sessionStorage.gameMainStage = 0 moveShip = function() { switch (sessionStorage.gameMainStage) { case '1': $("#object").animate( { crSpline: $.crSpline.buildSequence([[715, 425], [582, 524], [556, 646], [722, 688], [963, 629], [1143, 467]]) },{ duration: 10000, step: function() { var mover = $('#object'), posX = mover.position().left; posY = mover.position().top; $(window) .scrollLeft(posX - $(window).width() / 2) .scrollTop(posY - $(window).height() / 2); }, complete: function() { $.colorbox({href:"dialog-1.html", width:"737px", height:"474px", iframe: true, overlayClose: false, escKey: false, close: ""}); } } ); break; case '2': $("#object").animate( { crSpline: $.crSpline.buildSequence([[1143, 467], [1343, 667], [1443, 367], [1243, 167], [1499, 285]]) }, { duration: 5000, step: function() { var mover = $('#object'), posX = mover.position().left; posY = mover.position().top; $(window) .scrollLeft(posX - $(window).width() / 2) .scrollTop(posY - $(window).height() / 2); }, complete: function() { $.colorbox({href:"dialog-2", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""}); } } ); break; case '3': $("#object").animate( { crSpline: $.crSpline.buildSequence([[1499, 285], [1922, 423]]) }, { duration: 5000, step: function() { var mover = $('#object'), posX = mover.position().left; posY = mover.position().top; $(window) .scrollLeft(posX - $(window).width() / 2) .scrollTop(posY - $(window).height() / 2); }, complete: function() { $.colorbox({href:"dialog-3.html", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""}); } } ); break; case '4': $("#object").animate( { crSpline: $.crSpline.buildSequence([[1922, 423], [2216, 578]]) },{ duration: 5000, step: function() { var mover = $('#object'), posX = mover.position().left; posY = mover.position().top; $(window) .scrollLeft(posX - $(window).width() / 2) .scrollTop(posY - $(window).height() / 2); }, complete: function() { $.colorbox({href:"game-1.html", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""}); } } ); break; case '5': $("#object").animate( { crSpline: $.crSpline.buildSequence([[2216, 578], [2769, 904]]) },{ duration: 5000, step: function() { var mover = $('#object'), posX = mover.position().left; posY = mover.position().top; $(window) .scrollLeft(posX - $(window).width() / 2) .scrollTop(posY - $(window).height() / 2); }, complete: function() { $.colorbox({href:"dialog-4.html", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""}); } } ); break; case '6': $("#object").animate( { crSpline: $.crSpline.buildSequence([[2769, 904], [3263, 903]]) },{ duration: 5000, step: function() { var mover = $('#object'), posX = mover.position().left; posY = mover.position().top; $(window) .scrollLeft(posX - $(window).width() / 2) .scrollTop(posY - $(window).height() / 2); }, complete: function() { $.colorbox({href:"dialog-5.html", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""}); } } ); break; case '7': $.colorbox({href:"game-2.html", width:"500px", height:"600px", iframe: true, overlayClose: false, escKey: false, close: ""}); break; case '8': $.colorbox({href:"dialog-6.html", width:"737px", height:"567px", iframe: true, overlayClose: false, escKey: false, close: ""}); break; case '9': $("#object").animate( { crSpline: $.crSpline.buildSequence([[3263, 903], [4141, 820]]) },{ duration: 5000, step: function() { var mover = $('#object'), posX = mover.position().left; posY = mover.position().top; $(window) .scrollLeft(posX - $(window).width() / 2) .scrollTop(posY - $(window).height() / 2); }, complete: function() { $.colorbox({href:"dialog-7.html", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""}); } } ); break; case '10': $("#object").animate( { crSpline: $.crSpline.buildSequence([[4141, 820], [4568, 949], [4447, 1175]]) },{ duration: 5000, step: function() { var mover = $('#object'), posX = mover.position().left; posY = mover.position().top; $(window) .scrollLeft(posX - $(window).width() / 2) .scrollTop(posY - $(window).height() / 2); }, complete: function() { $.colorbox({href:"dialog-8.html", width:"737px", height:"434px", iframe: true, overlayClose: false, escKey: false, close: ""}); } } ); break; case '11': $.colorbox({href:"dialog-9.html", width:"737px", height:"567px", iframe: true, overlayClose: false, escKey: false, close: ""}); break; case '12': $("#object").animate( { crSpline: $.crSpline.buildSequence([[4447, 1175], [4701, 1124], [4816, 822]]) },{ duration: 5000, step: function() { var mover = $('#object'), posX = mover.position().left; posY = mover.position().top; $(window) .scrollLeft(posX - $(window).width() / 2) .scrollTop(posY - $(window).height() / 2); }, complete: function() { $.colorbox({href:"dialog-10.html", width:"900px", height:"687px", iframe: true, overlayClose: false, escKey: false, close: ""}); } } ); break; } }; })(jQuery); 
+6
source share
5 answers

I ran into this problem with a single page application that connected to window.resize and window.scroll. This was much slower in IE than in other browsers.

The first thing I noticed is that in IE (version 8, to be specific), the callback attached to window.scroll or .resize seems to have worked as many times as it did in Chrome or FF when the window was resized (or scrolling ) Thus, any callback is called several times more than Chrome, adding to its relative value.

We managed to solve our problem by minimizing what is done inside these callbacks to a minimum, and the main gain we had was getting rid of jQuery selectors. So in your case, you have, for example, var mover = $ ('# object') in the callback function, every time your event fires, IE tries to find and receive the object and wrap it in jQuery, just do it outside your callback, then use a cached object. In our case, it improved performance in order of magnitude, and it seemed that it was good even if there were no performance problems (it was an operation that was repeated unnecessarily).

So, in case 8, for example, there is something like:

  case '10':{ //caching myObject once and then use it afterwards var myObject = $("#object"), $window = $(window); myObject.animate( { crSpline: $.crSpline.buildSequence([[4141, 820], [4568, 949], [4447, 1175]]) }, { duration: 5000, step: function() { var mover = myObject, //no need to refetch the object posX = mover.position().left; posY = mover.position().top; $window.scrollLeft(posX - $window.width() / 2) .scrollTop(posY - $window.height() / 2); }, complete: function() { $.colorbox({href:"dialog-8.html", width:"737px", height:"434px", iframe: true, overlayClose: false, escKey: false, close: ""}); } } ); } 

ps: In addition, I'm not sure about the semantics of your application, but you may need to add your own logic to track posX and posY, since they can always refer to the original cached object, but in all cases follow the steps I mentioned to make sure that the cost of the selectors is the cause of the problem (as it was in my case).

+5
source

I am afraid that the library you are using is too old to expect great results.

I don’t see anything bad in your code (except that you could use a function with a config argument for each switch case, but this is just a refactoring issue that will not affect performance significantly)

CrSpline uses the left and top CSS properties.

Maybe you should take a look at CSS 2d transformations that use hardware acceleration:

Use -webkit/moz/ms-transform: translateX(-1000px) translateY(200px) instead of left: -1000px; top: 200px; left: -1000px; top: 200px;

I think you could easily rewrite some code in the crspline library in that direction.

You can also try to find a more modern library of splines.

Another point: crSpline does not seem to use the requestAnimationFrame function. The jQuery animate method doesn't work either. I would advise you to take a look at the TweenLite / TweenMax library: http://www.greensock.com/v12/

I welcome your work!

+11
source

First, you must optimize your code by creating a function for your animation (not tested, but should work):

 function animateMyObjet(duration,sequence,callback) { $("#object").animate( { crSpline: $.crSpline.buildSequence(sequence), { duration: duration, step: function() { var mover = $('#object'), posX = mover.position().left; posY = mover.position().top; $(window) .scrollLeft(posX - $(window).width() / 2) .scrollTop(posY - $(window).height() / 2); }, complete: function() { callback(); } } } 

Called in your code as follows:

 switch (sessionStorage.gameMainStage) { case '1': animateMyObjet(10000,[[715, 425], [582, 524], [556, 646], [722, 688], [963, 629], [1143, 467]], function() { $.colorbox({href:"dialog-1.html", width:"737px", height:"474px", iframe: true, overlayClose: false, escKey: false, close: ""}); break; case '2' : ... } 

Secondly, a few weeks ago I discovered that the number of web page elements affects IE9 performance. Try to hide all the elements that you do not need, because the element is hidden due to the scrollable container.

Sometimes the number of visible screen elements affects the animation characteristics. For the test, try reducing the size of the browser window and play the animation. I'm sure the animation will be smoother.

Hope these tips help you. Remember to post your final solution if you solve the problem.

And finally check out the potential related IE9 performance theme: IE9: there is always a little CPU usage on my website

+2
source

you can try to check if IE is working in a different mode than in IE9 browser mode and IE9 document mode, i.e. quirks or compatibility mode. If he tries to force him to use the standard. disable IE compatibility mode using tags

0
source

My idea is that if you call event handlers too often, it causes the event handlers to simply set a timeout (say, 10 ms) if there is no timeout at the moment and there is movement meat in the timeout function.

0
source

Source: https://habr.com/ru/post/928131/


All Articles