Javascript OnScroll performance comparison

user127091 picture user127091 · Jul 13, 2018 · Viewed 7.8k times · Source

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 or use this for old browsers: Scrolltest (the same, just not on 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...)

Answer

SirPeople picture SirPeople · Jul 20, 2018

I am not totally sure if I got correctly your questions and all your statements but I will try to give you an answer:

  • Am I missing something or is this a valid test? If it's invalid, how could I test correctly?

It is a valid test if you are measuring the number of times a function has been called, this will of course depend on the browser, SO, if is GPU enhanced and some other benchmark parameters that has been commented in your question already.

If we consider that measurement correct then it can be said that by using timeouts or requestAnimationFramework could save time because we are basically following the principles of debouncing or throttling. Basically we do not want to request or called a function more times than is needed. In the case of the timer we will queue less functions calls and in the case of requestAnimationFrame because it enqueue calls before repainting and will execute them sequentially. In timeouts it could happen that calculations overlap if they are very heavy.

I found a better answer in why using requestAnimationFrame explaining the main problems with animations in the browser like Shear, flickering or frame skip. It also includes a good demo.

I think your testing method is correct, you also should interpret it correctly, maybe calls are close to be the same number because of your hardware and your engine, but as said, debounce and throttling are a performance relieve.

Here also one more article supporting not attach handlers to window scroll from Twitter. (Disclaimer: this article is from 2011 and browsers have deal with optimizations for scroll in different ways).

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

I do not think there is nervousness in the performance hit, but the user experience will be worst for the above mentioned animation problems that your overcalling of scroll can cause, or even if there is a desynchronization with your timer you could still get the same 'performance' problems. People just recommend saving calls to scroll because: Human visual permanence doesnt require a super high frame rate and so it is useless to try to show images more often. For more complex calculations or heavy animations browsers are already working on optimizations, like you have check, some browsers had optimize this things in comparison with the 2, 3 or 6 years ago the articles you expose were written.