sveltejs / svelte

web development for the rest of us
https://svelte.dev
MIT License
79.81k stars 4.24k forks source link

Perf: Frequently updating reactive variables cause garbage collection pressure & hitching #4459

Open Ryan-McMillan opened 4 years ago

Ryan-McMillan commented 4 years ago

We're seeing some hitches in a game we're developing that uses embedded webkit(Coherent GT) for the UI and I've narrowed this down to what appears to be GC pressure created when using reactive variables.

We're updating reactive variables within our components nearly every frame for things like health & positions. In a normal web app, the GC times we're seeing(can get up to 20ms) wouldn't be an issue, but our UI has a small budget for each frame (~3ms).

I'm able to repro this in latest chrome with the following component in svelte 3.18.2:

<div data-amount="{amount}" />

<script>
let amount = 0;

setInterval(() => {
    amount = (amount + 1) % 100;
}, 4);
</script>

Here's what the memory looks like when profiling in chrome: image

A different approach that doesn't use reactive variables does not have this issue:

<div data-amount="{0}" bind:this={amountEl}/>

<script>
let amountEl;

setInterval(() => {
    amountEl.setAttribute("data-amount", (Number(amountEl.getAttribute("data-amount")) + 1) % 100);
}, 4);
</script>

Here's what the memory profile in chrome looks like when not using reactive variables: image

I've looked at the generated output and tried to narrow down what might be causing a lot of the extra allocation, but haven't been able to nail anything down yet. Any help would be appreciated!

pushkine commented 4 years ago

REPL : https://svelte.dev/repl/344426264c4540da9f79a60ad8b02d89?version=3.19.1

chrome_2020-02-25_15-38-12

the REPL is on dev mode though my guess is that it's from the svelte custom event dispatching