Search code examples
javascriptjqueryscrollonscroll

Javascript OnScroll performance comparison


Update: Similiar question with a very good answer that shows how to use requestAnimationFrame with scroll in a useful way: scroll events: requestAnimationFrame VS requestIdleCallback VS passive event listeners


So let's say I want to add some expensive action on my site triggered by scrolling. For example, I'm using parallax effects in my jsfiddle.

Now I keep reading it must not be bound to the event directly, sometimes followed by snippets that are meant to be better. Just some examples:

  1. Attaching JavaScript Handlers to Scroll Events = BAD!
  2. How to develop high performance onScroll event?
  3. How to make faster scroll effects?
  4. 60FPS onscroll event listener

What they say is basically don't do this:

  // Bad guy 1
  $(window).scroll( function() {
    animate(ex1);
  });

or this

  // Bad guy 2
  window.addEventListener('scroll', onScroll, false);
  function onScroll() {
    animate(ex2);
  }

But use timeouts, intervals, requestAnimationFrame and whatnot, for example:

  // Good guy
  $(window).scroll( function() {
   scrolling1 = true;
  });

  setInterval( function() {
    if (scrolling1) {
      scrolling1 = false;
      animate(ex3);
    }
  }, 50 );

So, I went and added the options I found in the links above to a jsfiddle that tries to compare them by adding a counter to every approach, like so:

  // Test
  $(window).scroll( function() {
    counter = counter + 1;
    // output result of counter
    animate(ex1);
  });

Best to check the complete jsfiddle

Outcome: Everything that works smooth is about the same number of calculations. If I can live with choppy effects, maybe I can safe some resources. And against everything I read, this seems logical to me!

First question: Am I missing something or is this a valid test? If it's invalid, how could I test correctly? Edit: To clarify, I want to test whether any of the above methods save performance at all.

Second question: If it is valid, why is everyone nervous about onscroll? If fluid animations require 5000 calculations over the complete site, there's no way to change it anyway?

(Well, sometimes I use checks to determine whether an object is in the viewport or not, but honestly I don't even know if those checks aren't as expensive as the prevented code itself, especially if they involve five different variables such as offset, windowHeight, scrolltTop, getBoundingClientRect and outerHeight...)


Solution

  • So, @SirPeople already answered your first question correctly, it is indeed a good test to see how often the animate function gets called, but it's a bad test to compare the performance of the different snippets.

    This is a performance recording of the excecution:

    performance test

    The function animate isn't expensive at all. I took a performance recording (next picture), which shows that it takes between 0.64ms and 1.29ms in the one iteration I looked at (points 1-5). And once the function is done, the repaint takes no time at all (point 6), which might be because the page has almost no content. When we take a look at the time, we can see that all five animation functions and the repaint happen in less than 10ms, which, under normal circumstances, mean that we can get a fluid 60fps animation (point 7).

    Also, if we want to compare onscroll event listeners we need to test each on it's own and compare the results. If one of the listeners would really be blocking it would have an influence on the whole page and without performance debugging you wouldn't know which one it was.

    I made two jsfiddles window.scroll and RAF. And, to my surprise, there does not seem to be any difference.

    Why are people concerned about this?

    As you can see in the jsfiddles linked above, if the event handlers get too large, the entire page is going to lag.

    Now what?

    I'm no performance guru myself, but: