svelte icon indicating copy to clipboard operation
svelte copied to clipboard

Svelte Deeply nested SVG's cause lag

Open SaintPepsi opened this issue 9 months ago • 14 comments

Describe the bug

When SVG elements are rendered to the page it causes a big performance slow down.

Parsing the HTML happens instantly, but then there is a presentation delay of over 500 ms

image image

Reproduction

https://github.com/SaintPepsi/unplugin-icons-performance-issue-minimal-reproduction

Logs

No response

System Info

System:
    OS: macOS 14.4.1
    CPU: (10) arm64 Apple M2 Pro
    Memory: 167.08 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 21.7.2 - /opt/homebrew/bin/node
    Yarn: 1.22.21 - ~/.nvm/versions/node/v18.16.1/bin/yarn
    npm: 10.6.0 - /opt/homebrew/bin/npm
    pnpm: 8.14.1 - ~/.nvm/versions/node/v18.16.1/bin/pnpm
    bun: 1.0.3 - ~/.bun/bin/bun
  Browsers:
    Chrome: 124.0.6367.91
    Safari: 17.4.1
  npmPackages:
    svelte: ^5.0.0-next.120 => 5.0.0-next.120

Severity

annoyance

SaintPepsi avatar Apr 30 '24 22:04 SaintPepsi

Thanks for the repro! I tried testing it, but I'm not seeing the same...

At most I'm seeing ~45ms presentation delay for all interactions, on both Mac (Safari/Chrome) and Windows (Chrome).

whalderman avatar May 01 '24 10:05 whalderman

I'm really sorry, I was in a rush to get to work when I posted this. It's only happening on Mobile for me, Android.

The screenshots are from running it from my Android phone connecting to my computer over wifi vite dev --host

SaintPepsi avatar May 01 '24 19:05 SaintPepsi

I just tried on iPad (Physical Device) and iPhone (Simulated) but it's not happening on those.

SaintPepsi avatar May 01 '24 19:05 SaintPepsi

also reported here https://github.com/unplugin/unplugin-icons/issues/357

(please mention cross-links in the future to avoid duplicated work)

from the comments there it appears you are using lots of event handlers.

Can you provide a minimal reproduction and upload the full trace to show where time is spent instead of just a screenshot?

dominikg avatar May 01 '24 19:05 dominikg

I Re-created the exact same scenario but in React, it's also not very quick but it's quicker than svelte: https://github.com/SaintPepsi/test-react-performance-issue

image

SaintPepsi avatar May 01 '24 20:05 SaintPepsi

(please mention cross-links in the future to avoid duplicated work)

Apologies, I've not done many issue reports

Can you provide a minimal reproduction and upload the full trace to show where time is spent instead of just a screenshot?

What do you mean when you say full trace? like this?

image

SaintPepsi avatar May 01 '24 20:05 SaintPepsi

image

If it's this I can't see the Event log / Call tree that deeply: image

The HTML Parse happens quickly as expected: image

But there's not actually anything happening for the whole time the frames are dropped image

I do see that the GPU Activity is taking a long time, but It doesn't make sense since it's just rendering a single svg image

SaintPepsi avatar May 01 '24 20:05 SaintPepsi

I've added another button in the minimal repro for rendering "many" children (9) this also gives performance problems and it's only 1 deep:

image

SaintPepsi avatar May 01 '24 20:05 SaintPepsi

I've added buttons for rendering pngs: https://github.com/SaintPepsi/unplugin-icons-performance-issue-minimal-reproduction/commit/0e70a4e12dae79f37b40a2cea6461e62dcdfdf03

They don't have any performance issue besides the normal delay of loading the image. Are SVG's just really expensive to render?

SaintPepsi avatar May 01 '24 20:05 SaintPepsi

Please can you create an example on the REPL? this is far easier for us to debug and track. It might be that we can apply some optimizations in some places, or are missing them entirely.

trueadm avatar May 02 '24 15:05 trueadm

No Worries @trueadm, I've created 2 examples. a REPL for svetle and a JSFiddle for Vanilla HTML + JS, I don't know how to use Svelte 5 in REPL so I can now see that it's not just a Svelte 5 issue but a svelte issue in general.

The REPL: https://svelte.dev/repl/aa9742961b954040b07d33b145a37cbf?version=4.2.15

The Fiddle: https://jsfiddle.net/SanCoca/3oh40xke/14/

In the Svelte REPL if you click on "Show Multiple Complex Exploding Head SVG"'s button, 10 SVG's get rendered I can see when running Performance Profiling that there's alot of SvelteDOMSetAttribute Events which appears to me as the thing that takes the most time because it happens for each DOM element in the SVG. this SVG in this case contains roughly 172 dom elements svgElement.querySelectorAll('*').length so that means for each of those elements it's creating that event even when nothing about the DOM element is tied to any logic. image

If you look at the fiddle, The tasks of duplicating each node and then insertBeforeing takes roughtly an avarage of 1 - 4ms. So then it's just the recalculation of the style and that's done. This screenshot is of 128 Complex SVG's being cloned and inserted. in about the same time it takes Svelte to render 10 complex SVG's image

I hope this is enough information to help out If there's more alternative examples that you'd like me to provide please let me know.

The issue has now transcended my mobile phone, it's obvious that phones score worse in performance. As these tests were replicated on my computer

SaintPepsi avatar May 02 '24 21:05 SaintPepsi

I know that the obvious solution here is "Don't use complex SVG's as images, just use a png" but I do think it's an interesting problem, and it could highlight other problems that might arise in the future, i've been committed to svelte for a couple of years now and i'm building my first Production application with it and as the complexity of my projects has been increasing as I get familiar with Svelte over the years I discover interesting kinks that are hard to spot in smaller applications that i'd love to help iron out, since i'm new to contributing I just need some extra guidance 🙇‍♂️ Love you @Rich-Harris

SaintPepsi avatar May 02 '24 21:05 SaintPepsi

@SaintPepsi Svelte 5 doesn't trigger any SvelteDOMSetAttribute events. In fact, converting the above to Svelte 5 for me results in rendering the "Show Multiple Complex Exploding Head SVG" taking less than 2.5ms to render. Do you have any browser extensions enabled that might be slowing this down? If you try private/incognito mode, does that help?

trueadm avatar May 02 '24 23:05 trueadm

@trueadm I noticed that as well yes. On my computer it's fine, but on Android it's quite slow. I spoke to @khromov and he mentioned there's an open chromium ticket for it too https://bugs.chromium.org/p/chromium/issues/detail?id=1289741

Seeing that svelte 5 does not have this issue and if all it is at the moment is a chromium bug then maybe this can be closed and an alternative solution should be explored like png's.

Thanks in any case for participation 🙂

SaintPepsi avatar May 03 '24 02:05 SaintPepsi

I'm going to close this, because the thing that is actually causing any sort of lag on svelte's side is fixed in Svelte 5 like @trueadm mentioned :) thanks again everyone

SaintPepsi avatar May 07 '24 09:05 SaintPepsi