Open Bug 1426295 Opened 6 years ago Updated 2 years ago

stylo: SVG images use more memory than Gecko

Categories

(Core :: CSS Parsing and Computation, defect, P2)

defect

Tracking

()

Tracking Status
firefox-esr52 --- unaffected
firefox57 --- wontfix
firefox58 --- affected
firefox59 --- affected

People

(Reporter: xidorn, Unassigned)

References

(Depends on 1 open bug)

Details

(Whiteboard: [MemShrink:P2])

See bug 1421374 comment 2, enabling stylo-chrome causes 10% regression on images memory usage, and that is from larger memory usage of SVG images in browser chrome.

We may need to understand why SVG images take 2%~6% more memory than Gecko, and probably fix it.
I thought we saw similar regression on content docs IIRC...

I suspect it's just because we persist style state on the Elements, and that takes up space that Gecko doesn't use I guess.

Either that or for some reason we do way worse at style sharing, but I suspect that's not really the case... In any case worth measuring ofc.
So I just get some memory reports for the image which regressed the most on win64, which is
> chrome://browser/skin/tracking-protection-16.svg#enabled

I opened this document in five tabs, and minimize the memory usage in about:memory, then save the reports. The result is:
─104,976 B (02.85%) -- top(chrome://browser/skin/tracking-protection-16.svg#enabled, id=NNN)/active/window(chrome://browser/skin/tracking-protection-16.svg#enabled)/layout
├──158,560 B (04.31%) -- servo-style-structs
│  ├───90,720 B (02.47%) ── Display [5] [+]
│  └───67,840 B (01.84%) ── sundries [5] [+]
├───86,640 B (02.36%) -- servo-style-sets
│   ├──44,640 B (01.21%) -- stylist
│   │  ├──21,600 B (00.59%) ── rule-tree [5] [+]
│   │  ├──10,240 B (00.28%) ── element-and-pseudos-maps [5] [+]
│   │  ├──10,240 B (00.28%) ── invalidation-map [5] [+]
│   │  └───2,560 B (00.07%) ── other [5] [+]
│   └──42,000 B (01.14%) ── other [5] [+]
├──-86,576 B (-2.35%) -- gecko-style-structs
│  ├──-50,880 B (-1.38%) ── Display [5] [-]
│  └──-35,696 B (-0.97%) ── sundries [5] [-]
├───62,560 B (01.70%) -- computed-values
│   ├──58,480 B (01.59%) ── dom [5] [+]
│   └───4,080 B (00.11%) ── non-dom [5] [+]
├──-57,968 B (-1.58%) ── pres-shell [5]
├──-35,200 B (-0.96%) ── style-contexts [5] [-]
├──-25,920 B (-0.70%) ── rule-nodes [5] [-]
├──-13,680 B (-0.37%) ── gecko-style-sets [5] [-]
├───10,240 B (00.28%) ── pres-contexts [5]
├────7,040 B (00.19%) ── servo-element-data-objects [5] [+]
└─────-720 B (-0.02%) ── style-sheets [5]

It seems we are almost 2x large on style structs allocated, on both display and others.

I guess by style state on elements, you mean computed-values here? That does seem to be a problem...
I wonder if we need to store the invalidation stuff in SVG-as-an-image. I suspect those documents are mostly static.
The content of SVG-as-image can indeed be affected by @media at least, so I suspect we really can get rid of invalidation stuff... How much it changes is a different question, though.

If it doesn't change a lot, maybe we can rebuild it when necessary...
There is one interesting thing that, tracking-protection-16.svg#enabled only have 23 elements in total (in which two would be descendants of a display:none element when #enabled). When expanding all the use nodes, there is going to be 28 elements for styling.

nsStyleDisplay has a size of 424 bytes, + refcount it would take 432 bytes (which is well aligned to 16 bytes bucket), so each document should take 432 * 28 = 12,096 bytes for nsStyleDisplay structs, and 5 documents should take 12,096 * 5 = 60,480 bytes at worst, but it takes 90,720 bytes above, 50% worse than the worst case estimated.

The worst possible number for Gecko would be 424 * 28 * 5 = 59,360 bytes, while it actually takes 50,880 bytes, which translates to 4 less instances per document (424 * 4 * 5 = 8480 bytes = 59,360 - 50,880) which is probably from sharing between the <path> elements and <mask> elements.
Oh, so invalidation map is for restyling when element state changes? Sounds like that's something we don't need to keep indeed. Script is not allowed in SVG-as-image. I'm not sure about how SMIL works. If that doesn't change element itself, it doesn't matter either, and we should be able to drop invalidation map in SVG-as-image.
Depends on: 1427679
Depends on: 1427681
Whiteboard: [MemShrink]
Blocks: 1438775
Whiteboard: [MemShrink] → [MemShrink:P1]
Whiteboard: [MemShrink:P1] → [MemShrink:P2]
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.