Jump to content
GreenSock

micahhauge

PLEASE HELP: Performance issue.

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

Hey guys, I just started using GSAP and so far I am very impressed. I am running into some performance issues though, so I could really use some help!


I am working on creating a web application that is kind of like a guitar hero for piano. I need the application to be able to animate a bunch of rectangles downward at a constant rate (each rectangle represents a note in a song). I am running into some performance issues though, since a song can contain thousands of individual notes. I have created a codepen that demonstrates what I am talking about. There is a stutter once and a while that I cannot stand. 


Here is a link to the codepen 


Let me know if you see a better way of doing this that will prevent the stutter.


Thanks, 


Micah Hauge


See the Pen EyJjGA?editors=0011 by MicahHauge (@MicahHauge) on CodePen

Link to comment
Share on other sites

Hello micahhauge, Hello , and Welcome to the GreenSock forum!

Thank you for the example, very helpful !!

 

You were using an old version of TweenMax.. we are now at version 1.19.0 :)

 

This is a browser issue due to the amount of DOM elements your trying to move at once within the entire viewport. Any time you try and animate 500 DOM elements at once, you will see jank (lost frames). You can see this by reducing the amount of notes to 50 or 100.

 

Also constantly removing and adding elements in the DOM while you are animating a large quantity of DOM elements will cause jank as well due to having to re-layout and paint those removed and added elements. Usually if you need to move a large amount of elements it is best to use canvas.

 

You can see here i forked your example and added:

  • paused: true in your TimelineLite constructor so the timeline does not play until your loops are done adding all the elements to the DOM
  • a slight rotation: 0.01
  • a slight translateZ offset .. z: 0.01 (to force matrix3D)
  • used a faster native JS method of appending elements in to the DOM using appendChild()
  • added pointer-event:none to your css for each note graphic
  • added overflow: hidden to the bodyso the scrollbar stopped pushing the viewport back and forth
  • used jquery on("load") instead of window load since load() is deprecated in jquery
  • added tl.play() to play after all timeline code was parsed above it
  • and most importantly added a document jquery ready() event so your code only runs when the DOM is ready

I removed the position absolute and float left you had on the body tag.. you should never add those CSS properties on the body tag :) Think of the body tag as your main stage. Also i removed the duplicate jquery and tweenmax you had in the HTML panel.

 

See the Pen rLbOZQ by jonathan (@jonathan) on CodePen

 

This is the same link but in codepen debug mode which loads the page without being loaded in an iframe:

 

http://s.codepen.io/jonathan/debug/rLbOZQ

 

After doing all of the above, when i comment out the call() to removeFromDom function you will see, or at least i see that the stutter goes away. Since the browser doesn't have to remove DOM elements. usually you should add display none to those elements that are not being animated, since removing hundreds of elements from the DOM will cause more jank while animating.

 

Just remember to only run your animation code after the DOM is ready and the window is fully loaded.

 

Also keep in mind when testing performance you always want to make sure you test in a private browsing or incognito mode tab so you performance results dont get skewed by extensions or having the dev tools open.

 

But again i this is more of a browser issue trying to move 500 DOM elements at once .. and then remove from the DOM that it is already animating. So the browser will have to constantly repaint and then re-layout causing layout thrashing causing jank. Canvas is best suited for animating hundreds of elements

 

I hope this helps! :)

  • Like 3
Link to comment
Share on other sites

Wow, I think Jonathan hit on everything perfectly.

 

Unfortunately the DOM wasn't built to be a fast-rendering game engine so there is just so much you can expect from it, unfortunately.

To be clear, GSAP executes extremely fast, but the browser has to do a lot of work to render the changes to all the properties that GSAP is changing.

 

 

Read the end of this thread where there is a similar discussion about scrolling too many DOM elements.

http://greensock.com/forums/topic/14916-loop-draggable-carousel/

 

Be sure to see Blake's demo that allows you to flick and scroll a hundred images. Hiding the elements instead of removing from DOM should help greatly.

http://codepen.io/osublake/pen/2716a24249f67d1179c5bdb0e9eb3489?editors=0010

 

I didn't have time to go through your code very thoroughly but instead of creating 1000 notes, just create enough to display on screen and re-use them.

So once a note falls below the viewport but it off to side until you need a new note.

 

Do some reading on "Object Pooling".

  • Like 3
Link to comment
Share on other sites

 

 

You can see here i forked your example and added:

  • paused: true in your TimelineLite constructor so the timeline does not play until your loops are done adding all the elements to the DOM
  • a slight rotation: 0.01
  • a slight translateZ offset .. z: 0.01 (to force matrix3D)
  • used a faster native JS method of appending elements in to the DOM using appendChild()
  • added pointer-event:none to your css for each note graphic
  • added overflow: hidden to the bodyso the scrollbar stopped pushing the viewport back and forth
  • used jquery on("load") instead of window load since load() is deprecated in jquery
  • added tl.play() to play after all timeline code was parsed above it
  • and most importantly added a document jquery ready() event so your code only runs when the DOM is ready

 

 

Just a small question on this: Is it the same to use force3D:true instead of translateZ and rotation? 

Link to comment
Share on other sites

  • 3 months later...

force3D will pretty much do the same thing for you so you dont have to use a this type of hack. Basically triggering the browser to create a new rendering layer for hardware acceleration. Once applied you should either see translate3d() or matrix3d() on your element being animated.

 

Happy Tweening!

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×