Handmade Network»Forums»Wheel Reinvention Jam
Gaurav Gautam
98 posts
Stepping through the debug build of safari to figure out why its taking too much memory?
Edited by Gaurav Gautam on

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: Screenshot 2023-01-08 at 8.08.34 AM.png

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:

Screenshot 2023-01-08 at 8.10.33 AM.png

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.

Screenshot 2023-01-08 at 1.49.37 PM.png

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. Screenshot 2023-01-08 at 3.47.04 PM.png

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.

Gaurav Gautam
98 posts
Stepping through the debug build of safari to figure out why its taking too much memory?
Edited by Gaurav Gautam on

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.

Edit

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.