Hey so recently I was trying to get the Page Size down for our webpage in safari. And in the process I found that most of it was because of one svg image.
Here is the image: https://d6d4ismr40iw.cloudfront.net/img/EventBlur_verybig.svg
If you open this image in safari and look at the vm tracker attached to the thread on mac you will see this:
It shows dirty size of over 1.15GB. My understanding of dirty size is that its the memory being used by the process actively that cannot be recreated by the os. So basically it really is memory that is critical and doing real work in application space.
If you open this image in chrome and look at that thread you see that the dirty size is very small:
I have also noted that inside this svg file there is a filter, whose dimensions directly affect how much size is taken up.
<defs> <filter id="filter2_dddf" x="0" y="0" width="2400.00" height="2400.00" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB" >
If I change the width and height here it correlates directly to memory usage. (These I read off of the timeline tab in safari dev tools and not from the Instruments profiles)
Filtersize | Page Size(mb) ------------------------------------ 300 | 90 600 | 150 1200 | 400 2400 | 900
So, why does safari take so much more memory?! I have the code for webkit on my local and I have tried to find the implementation of these tags in it. I don't see anything obviously wrong in there but Im no C++ expert.
So I compiled webkit in the hopes of stepping through as it renders that svg. It looks like safari keeps re-rendering this thing. I can see in the memory meter on the left that it drops to low values sometimes and then comes back up. Im guessing chrome just doesn't do that. However, I don't know how to confirm that aside from compiling chromium as well (im not too enthusiastic about that). Ill just try to figure out why this function is running again.
So, now in xcode I can see a memory graph. But I don't know how to make sense of this. I need to know what part of this is due to the image and what is just always there.
Those allocations don't really add up to the usage with was like 80mb. The problem should be in mallocs only right? Can't be in a dylib I hope.
I found that the memory is being allocated by the files in platform/graphics/filters/software
folder by the software appliers. But I don't know why it won't just get deallocated after its done with the rendering.
I think I get it now. Its not deallocating because the svg holds references to all the intermediate results:
<svg width="1440" height="850" viewBox="0 0 1440 850" fill="none" xmlns="http://www.w3.org/2000/svg" > <g clip-path="url(#clip0)"> <g opacity="0.1" filter="url(#filter2_dddf)"> <ellipse cx="171.191" cy="-191.706" rx="362.096" ry="384.578" transform="rotate(75 171.191 -191.706)" fill="url(#paint3_linear)" fill-opacity="0.4" /> </g> </g> <defs> <filter id="filter2_dddf" x="0" y="0" width="2400.00" height="2400.00" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB" > <feFlood flood-opacity="0" result="BackgroundImageFix" /> <feOffset dx="100" dy="100"/> <feGaussianBlur stdDeviation="20"/> <feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0" /> <feBlend mode="normal" in2="SourceAlpha" result="effect1_dropShadow" /> <feOffset dx="-100" dy="50"/> <feGaussianBlur stdDeviation="100"/> <feBlend mode="normal" in2="SourceAlpha" result="effect2_dropShadow" /> <feOffset dx="200" dy="-50"/> <feGaussianBlur stdDeviation="50"/> <feBlend mode="normal" in2="SourceAlpha" result="effect3_dropShadow" /> <feBlend mode="normal" in="SourceAlpha" in2="effect3_dropShadow" result="shape" /> </filter> </defs> </svg>
In this the <filter>
tag has many effects applied using the software appliers. And each one has a result
tag. And I think, those are forcing it to keep around all the intermediate results. I don't know if its possible to delete references using the svg tags somehow. But it does suggest to me that we shouldn't be doing effects using svg in webpages as it won't just render the image and then free up the resources it used to render it. It will just keep building up.