Web page uses too much memory (~100-140 MB) for no apparent reason

RESOLVED WONTFIX

Status

()

Firefox
Untriaged
RESOLVED WONTFIX
3 years ago
3 years ago

People

(Reporter: nivtwig, Unassigned)

Tracking

42 Branch
Points:
---

Firefox Tracking Flags

(Not tracked)

Details

(Whiteboard: [MemShrink], URL)

Attachments

(2 attachments)

(Reporter)

Description

3 years ago
User Agent: Mozilla/5.0 (Windows NT 6.1; rv:42.0) Gecko/20100101 Firefox/42.0
Build ID: 20150718030211

Steps to reproduce:

1. Open firefox with only about:blank tab. Notice the memory used (Private working set) with task manager, and with about:memory. 

2. Open and load the following web page, open another blank tab and move to the blank tab. Wait some time (1 minute for example).

http://rotter.net/cgi-bin/forum/dcboard.cgi?az=show_thread&om=228152&forum=scoops1&viewmode=all



Actual results:

3. Notice the additional memory used using 2 methods: task manager, and about:memory .
All methods show a memory increase of about 100-140 MB , caused by the web page, and that it persists and doesn't drop although you moved away from the tab, and this is not a selected and visible tab anymore.



Expected results:

I think the web page should have used much less memory.
It is a forum page with a lot of comments (490), but most of them text or simple html that shouldn't take too much memory.

Yes, the page has many images and embedded youtube videos, but since the tab is not visible I would assume most images memory could be discarded due to changes that I know were done in the past to improve image memory use, since the tab is not visible and I moved to another tab.

The page contains many youtube videos, but this should not be a reason for the large and persistent memory consumption even when I move to another tab.
First, the data about them can be discarded or be cached on disk until needed if youtube embedded videos that aren't played or used consume too much memory. Second, the about:memory report shows (under "active", under the window object for the tab) 11 youtube windows each consuming 3.22MB, totalling ~ 35MB . 
Even if we ignore or decrease the youtube videos memory from the total, that doesn't explain the rest of the memory used by the tab which should be ~50MB or more.
(Reporter)

Comment 1

3 years ago
I forgot to mention that this problem exists both in Nightly and the stable Firefox 39.0 .
(Reporter)

Updated

3 years ago
(Reporter)

Comment 2

3 years ago
Updated URL since the original no longer works :
http://rotter.net/forum/scoops1/228152.shtml
Can you attach an about:memory report? Additionally the output from about:support can be helpful for us to determine if add-ons or graphics settings are at fault.
Flags: needinfo?(nivtwig)
(Reporter)

Comment 4

3 years ago
It is not due to add-ons. 
I forgot to mention that I tried this without add-ons (in safe mode), and the additional memory due to loading this URL is more or less the same.

I may attach the reports you requested later if I have some time.
I can't reproduce. When I load the link I just get a blank page.

But 100--140 MiB for a single page is unlikely to be a problem. Lots of pages use that much memory. Often JavaScript memory usage is a large fraction of that -- *many* pages do lots of stuff with JavaScript that isn't obvious. If the memory usage is growing steadily over time, or if the memory usage is excessive compared to other browsers, then that is more likely to indicate a problem.

The about:memory reports will indicate exactly how the memory is being used. https://developer.mozilla.org/en-US/docs/Mozilla/Performance/about:memory has instructions on how to gather them.
(Reporter)

Comment 6

3 years ago
Created attachment 8637107 [details]
memory-report.json.gz

about:memory report using Nightly 42.0a1 (2015-07-21), on Windows 7 32bit, e10s disabled, not using addons (safe mode)
Flags: needinfo?(nivtwig)
(Reporter)

Comment 7

3 years ago
Created attachment 8637110 [details]
about:support raw data
(Reporter)

Comment 8

3 years ago
(In reply to Nicholas Nethercote [:njn] from comment #5)
> I can't reproduce. When I load the link I just get a blank page.

You probably used the original link I gave which doesn't work any more, and didn't notice comment 2 where I gave an updated URL (this is the URL also currently on the URL field of bugzilla)
The updated URL is: 
http://rotter.net/forum/scoops1/228152.shtml

> But 100--140 MiB for a single page is unlikely to be a problem. Lots of
> pages use that much memory. Often JavaScript memory usage is a large
> fraction of that -- *many* pages do lots of stuff with JavaScript that isn't
> obvious. If the memory usage is growing steadily over time, or if the memory
> usage is excessive compared to other browsers, then that is more likely to
> indicate a problem.

Other forum threads (usually shorter) on the same forum website consume much less memory, usually 10-20MB .
For example: http://rotter.net/forum/scoops1/231549.shtml uses 10-20MB .

It seems to me it is more reasonable that javascript memory can be big and more or less fixed on all forum pages, but should not grow that big with the growth of the page size or number of comments on the forum thread.
(Reporter)

Comment 9

3 years ago
As I said in the bug report, the page contains several embedded YouTube videos and as expected the about:memory report shows (under "active", under the window object for the tab) 11 YouTube windows each consuming 3.22MB, totalling ~ 35MB . 

I a closer examination of the memory report , under each and every YouTube window object, there is a JavaScript compartment ( js-compartment ), consuming almost exactly 2.18MB for each object, mot of it governed by classes. 

I assume/guess that these js-compartment and classes are the same or almost the same for all embedded YouTube videos, and that the classes code in memory is duplicated again and again with each YouTube video since the memory consumed is almost the same between videos. This of course is an guess that need to be verified.

My question is: why is this JavaScript memory duplicated for each YouTube video, can't it be shareable among all YouTube videos on the current tab, or even across all tabs and windows in the browser, that use the same YouTube JavaScript code?

If there is some context that these YouTube videos code use and need to know which is unique/specific to the specific YouTube video, like info about the current tab, and the current video, can't it be a parameter or global context object or variable that is changed for the shared code according to the current video, but the code is resident just once and not multiplied/duplicated in memory.
Every JS global needs its own compartment, so I assume each YouTube video is in its own iframe or something. We do make some attempt to share identical JS script, but knowing that all of the changes that the scripts make to their data structures would be difficult.
(Reporter)

Comment 11

3 years ago
(In reply to Andrew McCreight [:mccr8] from comment #10)

> We do make some attempt to share identical
> JS script, but knowing that all of the changes that the scripts make to
> their data structures would be difficult.

Thanks.
However this is somewhat unclear to me, can you explain and give more details? 
If you make some attempt to share identical JS scripts, then what is shared currently, and what is not, and why not? 
The fact is that these Youtube scripts don't seem to be shared according to the memory report. 

If I understand correctly, you wrote that the scripts make changes to their data structures and that it would be difficult to share them, but I suggested sharing the scripts code, not sharing data structures allocated or created by the scripts. 
Most of the scripts code apparently doesn't change, and is identical between different instances of the embedded Youtube videos.
(In reply to nivtwig from comment #11)
> If you make some attempt to share identical JS scripts, then what is shared
> currently, and what is not, and why not? 

I'm not sure of the details, and I may actually be wrong, sorry. I tried to look it up but I couldn't find anything.

> Most of the scripts code apparently doesn't change, and is identical between
> different instances of the embedded Youtube videos.

The "classes" thing you were saying was taking up most of the compartment is for the JS data structures. The scripts themselves, are listed as "scripts".

Anyways, as I said, I don't really know what I'm talking about so I'm going to bow out of the discussion.
Here's sample output from my browser for the link in comment 2:

> ├──159.37 MB (48.01%) -- top(http://rotter.net/forum/scoops1/228152.shtml, id=8)
> │  ├──130.24 MB (39.23%) -- active
> │  │  ├───55.26 MB (16.65%) -- window(http://rotter.net/forum/scoops1/228152.shtml)
> │  │  │   ├──23.94 MB (07.21%) -- layout
> │  │  │   │  ├──12.47 MB (03.76%) -- frames
> │  │  │   │  │  ├───8.34 MB (02.51%) ++ (13 tiny)
> │  │  │   │  │  └───4.13 MB (01.24%) ── nsInlineFrame
> │  │  │   │  ├───4.95 MB (01.49%) ── pres-contexts [6]
> │  │  │   │  ├───3.71 MB (01.12%) ── text-runs [2]
> │  │  │   │  └───2.81 MB (00.85%) ++ (6 tiny)
> │  │  │   ├──17.58 MB (05.30%) -- dom
> │  │  │   │  ├──12.40 MB (03.74%) ── element-nodes [6]
> │  │  │   │  ├───4.96 MB (01.50%) ── text-nodes [5]
> │  │  │   │  └───0.22 MB (00.07%) ++ (4 tiny)
> │  │  │   ├───8.05 MB (02.43%) -- js-compartment(http://rotter.net/forum/scoops1/228152.shtml, about:blank)
> │  │  │   │   ├──4.94 MB (01.49%) ++ classes
> │  │  │   │   └──3.11 MB (00.94%) ++ (8 tiny)
> │  │  │   ├───4.48 MB (01.35%) ++ js-compartment(http://rotter.net/forum/scoops1/228152.shtml)
> │  │  │   └───1.21 MB (00.36%) ++ (2 tiny)
> │  │  ├───11.64 MB (03.51%) ++ (18 tiny)
> │  │  ├────6.43 MB (01.94%) -- window(https://www.youtube.com/embed/uVUseO_54L0)
> │  │  │    ├──4.52 MB (01.36%) -- js-compartment(https://www.youtube.com/embed/uVUseO_54L0)
> │  │  │    │  ├──3.03 MB (00.91%) ++ classes
> │  │  │    │  ├──1.02 MB (00.31%) ++ baseline
> │  │  │    │  ├──0.21 MB (00.06%) ++ scripts
> │  │  │    │  ├──0.18 MB (00.05%) ++ type-inference
> │  │  │    │  ├──0.04 MB (00.01%) ── compartment-tables
> │  │  │    │  ├──0.03 MB (00.01%) ── ion-data
> │  │  │    │  └──0.01 MB (00.00%) ── sundries/malloc-heap
> │  │  │    └──1.91 MB (00.58%) -- (4 tiny)
> │  │  │       ├──1.13 MB (00.34%) ── style-sheets
> │  │  │       ├──0.63 MB (00.19%) ++ layout
> │  │  │       ├──0.14 MB (00.04%) ++ dom
> │  │  │       └──0.00 MB (00.00%) ── property-tables
> │  │  ├────6.42 MB (01.93%) -- window(https://www.youtube.com/embed/aGUdEOjCwvg)
> │  │  │    ├──4.51 MB (01.36%) ++ js-compartment(https://www.youtube.com/embed/aGUdEOjCwvg)
> │  │  │    └──1.91 MB (00.58%) ++ (4 tiny)
> │  │  ├────5.66 MB (01.71%) -- window(https://www.youtube.com/embed/r-IFFyR3nyI)
> │  │  │    ├──3.75 MB (01.13%) ++ js-compartment(https://www.youtube.com/embed/r-IFFyR3nyI)
> │  │  │    └──1.91 MB (00.58%) ++ (4 tiny)
> │  │  ├────5.66 MB (01.71%) -- window(https://www.youtube.com/embed/E3CvAqac6kg)
> │  │  │    ├──3.75 MB (01.13%) ++ js-compartment(https://www.youtube.com/embed/E3CvAqac6kg)
> │  │  │    └──1.92 MB (00.58%) ++ (4 tiny)
> │  │  ├────5.65 MB (01.70%) -- window(https://www.youtube.com/embed/BaCg6s59ugo)
> │  │  │    ├──3.74 MB (01.13%) ++ js-compartment(https://www.youtube.com/embed/BaCg6s59ugo)
> │  │  │    └──1.91 MB (00.58%) ++ (4 tiny)
> │  │  ├────5.64 MB (01.70%) -- window(https://www.youtube.com/embed/74x5LCvV2BY)
> │  │  │    ├──3.74 MB (01.13%) ++ js-compartment(https://www.youtube.com/embed/74x5LCvV2BY)
> │  │  │    └──1.91 MB (00.58%) ++ (4 tiny)
> │  │  ├────5.63 MB (01.70%) -- window(https://www.youtube.com/embed/r0Os4rVq7wY)
> │  │  │    ├──3.72 MB (01.12%) ++ js-compartment(https://www.youtube.com/embed/r0Os4rVq7wY)
> │  │  │    └──1.91 MB (00.58%) ++ (4 tiny)
> │  │  ├────5.63 MB (01.70%) -- window(https://www.youtube.com/embed/ZgX6jlM4yVI)
> │  │  │    ├──3.72 MB (01.12%) ++ js-compartment(https://www.youtube.com/embed/ZgX6jlM4yVI)
> │  │  │    └──1.91 MB (00.58%) ++ (4 tiny)
> │  │  ├────5.63 MB (01.70%) -- window(https://www.youtube.com/embed/H3UICJEOOc4)
> │  │  │    ├──3.72 MB (01.12%) ++ js-compartment(https://www.youtube.com/embed/H3UICJEOOc4)
> │  │  │    └──1.91 MB (00.58%) ++ (4 tiny)
> │  │  ├────5.63 MB (01.69%) -- window(https://www.youtube.com/embed/o-ivaR-AVb8)
> │  │  │    ├──3.72 MB (01.12%) ++ js-compartment(https://www.youtube.com/embed/o-ivaR-AVb8)
> │  │  │    └──1.91 MB (00.57%) ++ (4 tiny)
> │  │  └────5.35 MB (01.61%) -- window(https://www.youtube.com/embed/_jS5eJRrm84)
> │  │       ├──3.44 MB (01.04%) ++ js-compartment(https://www.youtube.com/embed/_jS5eJRrm84)
> │  │       └──1.91 MB (00.58%) ++ (4 tiny)
> │  ├───28.32 MB (08.53%) -- js-zone(0x7f0c63746800)
> │  │   ├───8.70 MB (02.62%) -- lazy-scripts
> │  │   │   ├──6.47 MB (01.95%) ── gc-heap
> │  │   │   └──2.23 MB (00.67%) ── malloc-heap
> │  │   ├───6.24 MB (01.88%) ── type-pool
> │  │   ├───5.70 MB (01.72%) -- object-groups
> │  │   │   ├──5.30 MB (01.60%) ── gc-heap
> │  │   │   └──0.39 MB (00.12%) ── malloc-heap
> │  │   ├───4.06 MB (01.22%) ── unused-gc-things
> │  │   └───3.62 MB (01.09%) ++ (4 tiny)
> │  └────0.82 MB (00.25%) ++ cached/window(about:sessionrestore)

It's fairly similar to the numbers in the attached memory report, though
they're higher. Probably because I'm using a 64-bit build.

There's nothing alarming here. It's a mixture of DOM+layout, due to the text
and formatting, and JS data structures. There is some repetition due to the
YouTube iframes, but that's hard to avoid. It all looks very much as expected.
(Reporter)

Comment 14

3 years ago
(In reply to Nicholas Nethercote [:njn] from comment #13)
> There is some repetition due to the
> YouTube iframes, but that's hard to avoid.

Why is it hard to avoid? 
My questions about sharing the javascript in comment 9 and comment 11, were left unanswered.
This isn't an easy question to answer, but I'll take a stab at it.

In our Javascript engine, SpiderMonkey, we isolate each global object and all the state hanging off it into a 'compartment'. This is great for security, because when an object in one compartment wants to get information from an object in another compartment, we can ensure that it has the security clearance to do so. The object gets back a 'cross-compartment wrapper', which contains exactly as much information about the object it's trying to access as it is allowed to see.

However, this also makes it more difficult to share state between compartments: the only state we can share is stuff that doesn't care what compartment it's in, like strings and (some) scripts.

In general, various copies of the same thing might also simply be in a different state. For instance if each copy used a random number to start its computation, they might end up doing completely different things. Of course that's not likely here (though these things might well contain timestamps and things internally that make them different), but it's difficult for the Javascript engine to *prove* that these things are identical, or that significant portions or their internal state is identical and will *stay* identical.

This is even true of functions - things might create otherwise identical functions that are in some way tied to their global, for instance through the value of 'this', or by holding a reference to another function that *is* dependent on the global, or by depending on the values in another function via closures. On a lower level, there might be many non-obvious ways in which things are connected.

Of course that doesn't mean it's impossible to do more sharing, but those are some reasons why it's difficult.
nivtwig, thank you for the thorough report. We're going to close this as WONTFIX as the memory usage is in line with what we'd expect. Hopefully the details from Andrew, Nicholas, and Emanuel have helped explain what's going on.
Status: UNCONFIRMED → RESOLVED
Last Resolved: 3 years ago
Resolution: --- → WONTFIX
You need to log in before you can comment on or make changes to this bug.