I have a project in svelte that I was developing and feels good.
but when I go to my android phone I see that when click it is delayed a lot.
from what I know svelte is the fastest framework because uses native javascript code as output (no virtual dom) but what is happening here is out of the world (inexplicable)
1000000x slower? what? how it even possible
so I started debugging and investigating.
and I found that without transition everything was fine, speed is good and everything.
but when starting using transition slow the website.
debugging
with chrome devtools
when only adding transition:scale
like this <div transition:scale>
like you see more than 80% of speed is because that scale transition
the solution
without transition:scale
❌before | ✅now |
---|---|
3.12s | 5μs |
I'm not gonna lie but is like 1000000x faster than the with animation one.
why? this happens
I know the solution, but I need some explanation or a way to have animation without very very slow things.
the images you see on the top are the result of a very fast click on the button (like at least 20 times)
CodePudding user response:
This is called layout thrashing. It happens when you change or transitions CSS properties that cause style/layout recalculation. If these kinds of changes are applied to a list of many items, each one invalidates the calculations that came before it, wasting huge amounts of CPU time. (All the very small purple blocks at the bottom of the flame chart hint at this.)
To avoid this, you have to restrict your changes/transitions to those that do not cause these updates. The key here is that some properties like transform
do not affect layout and happen in the compositor which is a GPU accelerated operation.
Also, even compositor transitions are not "free", so applying them to many individual items at the same time should be avoided.
I looked at the trace in detail because the Svelte transitions themselves are already compositor-only; the creation of the animation appears to cause style recalculation & layout:
This is probably because this code interacts with the style.animation
property.
So either do not transition many items at once, or try class-based transitions.
Example for comparing the performance:
<script>
import { scale } from 'svelte/transition';
let count = 1000;
let svelte;
let classBased;
</script>
<label>
Item count
<input type=number bind:value={count} />
</label>
<label>
<input type=checkbox bind:checked={svelte}/>
Svelte transition
</label>
<label>
<input type=checkbox bind:checked={classBased}/>
Class transition
</label>
{#each { length: count } as i}
{#if svelte}
<h1 transition:scale={{duration: 300}}>Hello</h1>
{/if}
{/each}
{#each { length: count } as i}
<h1 class:show={classBased}>Hello</h1>
{/each}
<style>
.transition {
visibility: hidden;
transform: scale(0);
opacity: 0;
transition: opacity 0.3s, transform 0.3s, visibility 0s 0.3s;
}
.transition.show {
visibility: visible;
opacity: 1;
transform: scale(1);
transition: opacity 0.3s, transform 0.3s;
}
</style>