Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance: Cache ProxyAnimation instances #84

Merged
merged 5 commits into from
Oct 11, 2022

Conversation

bramus
Copy link
Collaborator

@bramus bramus commented Oct 4, 2022

Currently, the CSS polyfill creates new ProxyAnimation instances every time an animation starts. As you’re scrolling back and forth, you can see performance stutter.

This PR caches created instances onto the targeted elements, which improves performance.

Tested using the demo from https://codepen.io/bramus/pen/GRdGoKy, the performance timelines look like this:

Before After

@bramus
Copy link
Collaborator Author

bramus commented Oct 11, 2022

FYI: Rebased this branch onto master to make sure it can be merged easily.

const proxyAnimation = new ProxyAnimation(anim, result.timeline, result.animOptions);
// Create a cache on the element, to store all Proxy Animations in
if (!evt.target.proxiedAnimations) {
evt.target.proxiedAnimations = new Map();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not hang new stuff off element as it breaks encapsulation. We have animation and timeline details to avoid exposing polyfill internals to the outside world.

Instead we can add a global element map to the polyfill, i.e.:

let elementAnimationsMap = new WeakMap();

and then retrieve the map of proxied animations from there. Please take a look at how proxyAnimations.get(...) is used to retrieve animation details without exposing to the "outside world". We should follow the same pattern here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 3fb2b7f.

Note I could not use a WeakMap for the nested cache, as WeakMaps require Objects as their key. As the used anim always is a new Object, this didn’t work – it only created more Objects.

Using WeakMap Using Map
image image

@kevers-google kevers-google merged commit 573ca0a into flackr:master Oct 11, 2022
const elementProxyAnimations = proxyAnimations.get(evt.target);

// Store Proxy Animation in the cache
if (!elementProxyAnimations.has(anim.animationName)) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

animation-name allows listing the same animation more than once, e.g.

#target {
  animation-name: spin, spin;
}

This is expected to produce 2 animations with the latter having a higher composite order, but I believe this change will result in a single animation.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll need to track the index as well as the name.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created an alternative version in #89 which also implements getAnimations support in this polyfill.

flackr pushed a commit that referenced this pull request Oct 11, 2022
…mations

This makes document.getAnimations and Element.getAnimations correctly
return proxied instances of the animation so as to behave as expected.
Also by getting the proxied animations we can intelligently reuse the
existing proxied CSS animation when only timing details have changed
which implicitly fixes the performance issue of #84.
@bramus bramus deleted the quick-perf-win branch September 13, 2023 08:07
flackr added a commit that referenced this pull request Dec 21, 2023
…tions (#89)

This makes document.getAnimations and Element.getAnimations correctly
return proxied instances of the animation so as to behave as expected.
Also by getting the proxied animations we can intelligently reuse the
existing proxied CSS animation when only timing details have changed
which implicitly fixes the performance issue of #84.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants