svelte
svelte copied to clipboard
Svelte Deeply nested SVG's cause lag
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
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
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).
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
I just tried on iPad (Physical Device) and iPhone (Simulated) but it's not happening on those.
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?
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
(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?
If it's this I can't see the Event log / Call tree that deeply:
The HTML Parse happens quickly as expected:
But there's not actually anything happening for the whole time the frames are dropped
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
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:
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?
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.
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.
If you look at the fiddle, The tasks of duplicating each node and then insertBefore
ing 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
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
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 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 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 🙂
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