Closed
Bug 664642
Opened 14 years ago
Closed 14 years ago
Freeing decoded images doesn't reduce memory usage on Linux
Categories
(Core :: Graphics: ImageLib, defect)
Tracking
()
RESOLVED
INVALID
People
(Reporter: justin.lebar+bug, Unassigned)
Details
(Whiteboard: [MemShrink])
Attachments
(5 files, 1 obsolete file)
This may be a bug with the allocator and not imagelib.
* Set image.mem.discard_timeout_ms to 3000
* Load the attached page (full-size pictures from [1]). Thank Wikimedia for their bandwidth.
* Load about:memory without knocking the images out of memory (e.g. with the attached page focused, type "about:memory" into the location bar and press alt+enter to open in a new tab).
* Switch to about:memory tab and copy-paste the stats somewhere.
* Wait a few seconds for the images to be discarded, then refresh about:memory.
* Switch back to images tab and make sure that images were discarded before you refreshed.
* Switch back to about:memory tab and compare results from after discard to before discard.
My about:memory from before and after the discard is included below. Notice that although imagelib does free the relevant memory, it's never returned to the OS.
I understand that jemalloc may hold on to free'd memory, and that it's now available for other uses. But if ever there's a time to return memory to the OS, it's right after we free 380mb of image data. The perception that Firefox grabs on to memory and never lets go doesn't seem so far off here.
The numbers in about:memory don't add up, and I'm not sure how to interpret that. For instance, in the before discard case, it claims 460m of image data plus 220m of JS equals 510m of explicit allocations. The decoded image data has size 390m, but after discard only 170m is "heap-unclassified". Where'd the rest of the space go? Maybe njn can shed some light on this.
***** Before discard:
508.56 MB (100.0%) -- explicit
├──460.65 MB (90.58%) -- images
│ ├──460.55 MB (90.56%) -- content
│ │ ├──460.55 MB (90.56%) -- used
│ │ │ ├──388.87 MB (76.46%) -- uncompressed
│ │ │ └───71.68 MB (14.09%) -- raw
│ │ └────0.00 MB (00.00%) -- (1 omitted)
│ └────0.11 MB (00.02%) -- (1 omitted)
├──217.99 MB (42.86%) -- js
│ ├──149.00 MB (29.30%) -- gc-heap
│ ├───33.28 MB (06.54%) -- mjit-code
│ ├───23.22 MB (04.57%) -- tjit-data
│ │ ├──17.50 MB (03.44%) -- allocators-reserve
│ │ └───5.72 MB (01.12%) -- allocators-main
│ ├────8.00 MB (01.57%) -- stack
│ ├────2.99 MB (00.59%) -- mjit-data
│ └────1.50 MB (00.29%) -- (1 omitted)
├───34.95 MB (06.87%) -- storage
│ └──34.95 MB (06.87%) -- sqlite
│ ├──29.56 MB (05.81%) -- places.sqlite
│ │ ├──29.10 MB (05.72%) -- cache-used
│ │ └───0.46 MB (00.09%) -- (2 omitted)
│ └───5.38 MB (01.06%) -- (13 omitted)
├────6.23 MB (01.23%) -- layout
│ ├──6.23 MB (01.22%) -- all
│ └──0.00 MB (00.00%) -- (1 omitted)
└──-211.26 MB (-41.54%) -- (1 omitted)
Other Measurements
1,350.72 MB -- vsize
703.00 MB -- heap-committed
562.39 MB -- resident
465.78 MB -- heap-used
237.22 MB -- heap-unused
3.30 MB -- heap-dirty
1.44 MB -- canvas-2d-pixel-bytes
0.05 MB -- gfx-surface-image
**** After discard:
502.15 MB (100.0%) -- explicit
├──215.50 MB (42.91%) -- js
│ ├──149.00 MB (29.67%) -- gc-heap
│ ├───31.78 MB (06.33%) -- mjit-code
│ ├───22.62 MB (04.51%) -- tjit-data
│ │ ├──17.08 MB (03.40%) -- allocators-reserve
│ │ └───5.55 MB (01.10%) -- allocators-main
│ ├────8.00 MB (01.59%) -- stack
│ ├────2.72 MB (00.54%) -- mjit-data
│ └────1.38 MB (00.27%) -- (1 omitted)
├──173.62 MB (34.58%) -- heap-unclassified
├───71.86 MB (14.31%) -- images
│ ├──71.75 MB (14.29%) -- content
│ │ ├──71.75 MB (14.29%) -- used
│ │ │ ├──71.68 MB (14.27%) -- raw
│ │ │ └───0.08 MB (00.01%) -- (1 omitted)
│ │ └───0.00 MB (00.00%) -- (1 omitted)
│ └───0.11 MB (00.02%) -- (1 omitted)
├───34.95 MB (06.96%) -- storage
│ └──34.95 MB (06.96%) -- sqlite
│ ├──29.56 MB (05.89%) -- places.sqlite
│ │ ├──29.10 MB (05.79%) -- cache-used
│ │ └───0.46 MB (00.09%) -- (2 omitted)
│ └───5.38 MB (01.07%) -- (13 omitted)
└────6.23 MB (01.24%) -- layout
├──6.23 MB (01.24%) -- all
└──0.00 MB (00.00%) -- (1 omitted)
Other Measurements
1,349.09 MB -- vsize
703.00 MB -- heap-committed
557.51 MB -- resident
461.00 MB -- heap-used
242.00 MB -- heap-unused
2.13 MB -- heap-dirty
1.20 MB -- canvas-2d-pixel-bytes
0.05 MB -- gfx-surface-image
[1] http://commons.wikimedia.org/wiki/Commons:Picture_of_the_Year/2009/Finalists
Comment 1•14 years ago
|
||
I'll note I just saw a checkin to fix double-counting of some image allocations for about:memory, so that may be part of it
Comment 2•14 years ago
|
||
(In reply to comment #0)
> └──-211.26 MB (-41.54%) -- (1 omitted)
Note that this negative value is weird and somehow biases the total value before discard.
Comment 3•14 years ago
|
||
Note that to debug these kind of things, it would be useful to have a view of jemalloc arenas use.
![]() |
||
Comment 4•14 years ago
|
||
(In reply to comment #0)
>
> I understand that jemalloc may hold on to free'd memory, and that it's now
> available for other uses. But if ever there's a time to return memory to
> the OS, it's right after we free 380mb of image data. The perception that
> Firefox grabs on to memory and never lets go doesn't seem so far off here.
Depends what people are measuring. This one doesn't worry me that much. My philosophy is to assume jemalloc knows what it's doing. It's paging that matters the most, and that memory won't cause paging. (Address space exhaustion on 32-bit is more of an issue, admittedly.)
> The numbers in about:memory don't add up,
>
> └──-211.26 MB (-41.54%) -- (1 omitted)
The key here is the negative number, which is easy to miss. Is your repo more than 10 days old? If so, it is probably bug 658814. If you can paste the verbose about:memory (click the "more verbose" link at the bottom, or go straight to "about:memory?verbose") it'll be clearer what's happening.
![]() |
||
Updated•14 years ago
|
Whiteboard: [MemShrink]
Reporter | ||
Comment 5•14 years ago
|
||
> It's paging that matters the most, and that memory won't cause paging.
If someone else needs the memory, the OS will have to page us out. It probably won't pick the right pages to kick out, so when we're refocused, we may have to page in before we're responsive. And even if the OS did choose to page out these inactive pages, as soon as the allocator reuses them for something else, we have to page them in!
This is happening on the 2011-06-15 nightly. I'll paste verbose stats in a moment.
Comment 6•14 years ago
|
||
I constantly run into memory space exhaustion on Win32 (I keep a silly number of tabs open - bad habit) and frequently crash at that point (4.0.1). I run a clone of that profile on a recent nightly (on unix) and things seem better, but I haven't pushed it yet. When we get close to exhausted, minor scrolls and other operations will often invoke 10-200 seconds of max system CPU use with a frozen program.
Reporter | ||
Comment 7•14 years ago
|
||
Verbose output.
***** Before discard
Main Process
Explicit Allocations
512,956,810 B (100.0%) -- explicit
├──215,790,800 B (42.07%) -- js
│ ├──153,092,096 B (29.85%) -- gc-heap
│ ├───30,699,520 B (05.98%) -- mjit-code
│ ├───19,239,168 B (03.75%) -- tjit-data
│ │ ├──14,208,000 B (02.77%) -- allocators-reserve
│ │ └───5,031,168 B (00.98%) -- allocators-main
│ ├────8,388,608 B (01.64%) -- stack
│ ├────3,191,760 B (00.62%) -- mjit-data
│ └────1,179,648 B (00.23%) -- tjit-code
├──177,975,496 B (34.70%) -- heap-unclassified
├───76,721,509 B (14.96%) -- images
│ ├──75,775,493 B (14.77%) -- content
│ │ ├──75,771,958 B (14.77%) -- used
│ │ │ ├──75,688,382 B (14.76%) -- raw
│ │ │ └──────83,576 B (00.02%) -- uncompressed
│ │ └───────3,535 B (00.00%) -- unused
│ │ ├──3,535 B (00.00%) -- raw
│ │ └──────0 B (00.00%) -- uncompressed
│ └─────946,016 B (00.18%) -- chrome
│ ├──944,992 B (00.18%) -- used
│ │ ├──944,992 B (00.18%) -- uncompressed
│ │ └────────0 B (00.00%) -- raw
│ └────1,024 B (00.00%) -- unused
│ ├──1,024 B (00.00%) -- uncompressed
│ └──────0 B (00.00%) -- raw
├───36,763,712 B (07.17%) -- storage
│ └──36,763,712 B (07.17%) -- sqlite
│ ├──31,093,552 B (06.06%) -- places.sqlite
│ │ ├──30,608,584 B (05.97%) -- cache-used
│ │ ├─────406,552 B (00.08%) -- stmt-used
│ │ └──────78,416 B (00.02%) -- schema-used
│ ├───1,049,224 B (00.20%) -- other
│ ├─────940,680 B (00.18%) -- cookies.sqlite
│ │ ├──924,968 B (00.18%) -- cache-used
│ │ ├───12,752 B (00.00%) -- stmt-used
│ │ └────2,960 B (00.00%) -- schema-used
│ ├─────633,480 B (00.12%) -- webappsstore.sqlite
│ │ ├──562,144 B (00.11%) -- cache-used
│ │ ├───64,984 B (00.01%) -- stmt-used
│ │ └────6,352 B (00.00%) -- schema-used
│ ├─────558,008 B (00.11%) -- formhistory.sqlite
│ │ ├──396,728 B (00.08%) -- cache-used
│ │ ├──158,616 B (00.03%) -- stmt-used
│ │ └────2,664 B (00.00%) -- schema-used
│ ├─────466,912 B (00.09%) -- extensions.sqlite
│ │ ├──363,704 B (00.07%) -- cache-used
│ │ ├───92,040 B (00.02%) -- stmt-used
│ │ └───11,168 B (00.00%) -- schema-used
│ ├─────402,872 B (00.08%) -- urlclassifier3.sqlite
│ │ ├──297,688 B (00.06%) -- cache-used
│ │ ├──100,944 B (00.02%) -- stmt-used
│ │ └────4,240 B (00.00%) -- schema-used
│ ├─────381,360 B (00.07%) -- signons.sqlite
│ │ ├──330,680 B (00.06%) -- cache-used
│ │ ├───46,160 B (00.01%) -- stmt-used
│ │ └────4,520 B (00.00%) -- schema-used
│ ├─────341,368 B (00.07%) -- addons.sqlite
│ │ ├──264,648 B (00.05%) -- cache-used
│ │ ├───69,760 B (00.01%) -- stmt-used
│ │ └────6,960 B (00.00%) -- schema-used
│ ├─────305,632 B (00.06%) -- content-prefs.sqlite
│ │ ├──264,664 B (00.05%) -- cache-used
│ │ ├───36,920 B (00.01%) -- stmt-used
│ │ └────4,048 B (00.00%) -- schema-used
│ ├─────269,512 B (00.05%) -- chromeappsstore.sqlite
│ │ ├──198,976 B (00.04%) -- cache-used
│ │ ├───64,184 B (00.01%) -- stmt-used
│ │ └────6,352 B (00.00%) -- schema-used
│ ├─────109,168 B (00.02%) -- downloads.sqlite
│ │ ├───99,576 B (00.02%) -- cache-used
│ │ ├────6,768 B (00.00%) -- stmt-used
│ │ └────2,824 B (00.00%) -- schema-used
│ ├─────108,416 B (00.02%) -- permissions.sqlite
│ │ ├───99,584 B (00.02%) -- cache-used
│ │ ├────6,776 B (00.00%) -- stmt-used
│ │ └────2,056 B (00.00%) -- schema-used
│ └─────103,528 B (00.02%) -- search.sqlite
│ ├───99,568 B (00.02%) -- cache-used
│ ├────2,000 B (00.00%) -- schema-used
│ └────1,960 B (00.00%) -- stmt-used
└────5,705,293 B (01.11%) -- layout
├──5,704,125 B (01.11%) -- all
└──────1,168 B (00.00%) -- bidi
Other Measurements
1,413,173,248 B -- vsize
735,051,776 B -- heap-committed
574,558,208 B -- resident
472,689,034 B -- heap-used
262,361,876 B -- heap-unused
3,612,672 B -- heap-dirty
1,255,840 B -- canvas-2d-pixel-bytes
83,696 B -- gfx-surface-image
***** After discard
515,309,784 B (100.0%) -- explicit
├──216,408,140 B (42.00%) -- js
│ ├──153,092,096 B (29.71%) -- gc-heap
│ ├───31,297,536 B (06.07%) -- mjit-code
│ ├───19,061,272 B (03.70%) -- tjit-data
│ │ ├──14,060,000 B (02.73%) -- allocators-reserve
│ │ └───5,001,272 B (00.97%) -- allocators-main
│ ├────8,388,608 B (01.63%) -- stack
│ ├────3,388,980 B (00.66%) -- mjit-data
│ └────1,179,648 B (00.23%) -- tjit-code
├──179,606,773 B (34.85%) -- heap-unclassified
├───76,732,350 B (14.89%) -- images
│ ├──75,787,358 B (14.71%) -- content
│ │ ├──75,787,358 B (14.71%) -- used
│ │ │ ├──75,688,382 B (14.69%) -- raw
│ │ │ └──────98,976 B (00.02%) -- uncompressed
│ │ └───────────0 B (00.00%) -- unused
│ │ ├──0 B (00.00%) -- raw
│ │ └──0 B (00.00%) -- uncompressed
│ └─────944,992 B (00.18%) -- chrome
│ ├──944,992 B (00.18%) -- used
│ │ ├──944,992 B (00.18%) -- uncompressed
│ │ └────────0 B (00.00%) -- raw
│ └────────0 B (00.00%) -- unused
│ ├──0 B (00.00%) -- raw
│ └──0 B (00.00%) -- uncompressed
├───36,796,728 B (07.14%) -- storage
│ └──36,796,728 B (07.14%) -- sqlite
│ ├──31,093,552 B (06.03%) -- places.sqlite
│ │ ├──30,608,584 B (05.94%) -- cache-used
│ │ ├─────406,552 B (00.08%) -- stmt-used
│ │ └──────78,416 B (00.02%) -- schema-used
│ ├───1,049,224 B (00.20%) -- other
│ ├─────940,680 B (00.18%) -- cookies.sqlite
│ │ ├──924,968 B (00.18%) -- cache-used
│ │ ├───12,752 B (00.00%) -- stmt-used
│ │ └────2,960 B (00.00%) -- schema-used
│ ├─────633,480 B (00.12%) -- webappsstore.sqlite
│ │ ├──562,144 B (00.11%) -- cache-used
│ │ ├───64,984 B (00.01%) -- stmt-used
│ │ └────6,352 B (00.00%) -- schema-used
│ ├─────558,008 B (00.11%) -- formhistory.sqlite
│ │ ├──396,728 B (00.08%) -- cache-used
│ │ ├──158,616 B (00.03%) -- stmt-used
│ │ └────2,664 B (00.00%) -- schema-used
│ ├─────466,912 B (00.09%) -- extensions.sqlite
│ │ ├──363,704 B (00.07%) -- cache-used
│ │ ├───92,040 B (00.02%) -- stmt-used
│ │ └───11,168 B (00.00%) -- schema-used
│ ├─────435,888 B (00.08%) -- urlclassifier3.sqlite
│ │ ├──330,704 B (00.06%) -- cache-used
│ │ ├──100,944 B (00.02%) -- stmt-used
│ │ └────4,240 B (00.00%) -- schema-used
│ ├─────381,360 B (00.07%) -- signons.sqlite
│ │ ├──330,680 B (00.06%) -- cache-used
│ │ ├───46,160 B (00.01%) -- stmt-used
│ │ └────4,520 B (00.00%) -- schema-used
│ ├─────341,368 B (00.07%) -- addons.sqlite
│ │ ├──264,648 B (00.05%) -- cache-used
│ │ ├───69,760 B (00.01%) -- stmt-used
│ │ └────6,960 B (00.00%) -- schema-used
│ ├─────305,632 B (00.06%) -- content-prefs.sqlite
│ │ ├──264,664 B (00.05%) -- cache-used
│ │ ├───36,920 B (00.01%) -- stmt-used
│ │ └────4,048 B (00.00%) -- schema-used
│ ├─────269,512 B (00.05%) -- chromeappsstore.sqlite
│ │ ├──198,976 B (00.04%) -- cache-used
│ │ ├───64,184 B (00.01%) -- stmt-used
│ │ └────6,352 B (00.00%) -- schema-used
│ ├─────109,168 B (00.02%) -- downloads.sqlite
│ │ ├───99,576 B (00.02%) -- cache-used
│ │ ├────6,768 B (00.00%) -- stmt-used
│ │ └────2,824 B (00.00%) -- schema-used
│ ├─────108,416 B (00.02%) -- permissions.sqlite
│ │ ├───99,584 B (00.02%) -- cache-used
│ │ ├────6,776 B (00.00%) -- stmt-used
│ │ └────2,056 B (00.00%) -- schema-used
│ └─────103,528 B (00.02%) -- search.sqlite
│ ├───99,568 B (00.02%) -- cache-used
│ ├────2,000 B (00.00%) -- schema-used
│ └────1,960 B (00.00%) -- stmt-used
└────5,765,793 B (01.12%) -- layout
├──5,764,625 B (01.12%) -- all
└──────1,168 B (00.00%) -- bidi
Other Measurements
1,413,779,456 B -- vsize
735,051,776 B -- heap-committed
576,462,848 B -- resident
474,443,992 B -- heap-used
260,606,918 B -- heap-unused
4,014,080 B -- heap-dirty
1,507,008 B -- canvas-2d-pixel-bytes
83,696 B -- gfx-surface-image
So the memory is still entrained in imagelib? ...
Comment 10•14 years ago
|
||
We could use MALLOC_STATS output from a case like this too.
je_malloc.c:3337 should be freeing the "large" (>=4K, < 1MB) allocations if it thinks the entire allocation is free - note that "large" chunks are ~1MB it appears, so parts may be shared by other users. 'Huge' allocations >=1MB should be going more directly back to be unmapped.
Note that image data is NOT isolated from general-usage heap/mmap data. They're indirectly semi-isolated because they tend to be 'large' or 'huge', but large starts at 4k.
It would be interesting (though I probably wouldn't release it this way) to see what happens if the image allocators (gfxsurface(JPEG), PNG, GIF, etc) were temporarily switched to use a separate arena...
Comment 11•14 years ago
|
||
I'm going to switch this to Core :: jemalloc for now, because I'm quite sure that imagelib frees the memory it allocates. If that's wrong, please move this bug back.
Component: ImageLib → jemalloc
QA Contact: imagelib → jemalloc
Reporter | ||
Updated•14 years ago
|
Summary: Discarding images doesn't reduce memory usage → Freeing large chunks of malloc'ed memory (e.g. decoded images) doesn't reduce memory usage
Should be easy to figure out if jemalloc is the culprit ... is this reproducible on Mac?
Reporter | ||
Comment 13•14 years ago
|
||
Here are the mac results. Resident size goes down from 862m to 670m (-192m). about:memory says that the decoded images take up 388m, although if we're double-counting that, then the 192 would account for almost all the space.
Reporter | ||
Comment 14•14 years ago
|
||
I just tested on Windows, and it appears that we do release there too.
On IRC, khuey suggested that the problem might be [1], but stuart is skeptical.
[1] http://hg.mozilla.org/mozilla-central/file/079c171b6323/memory/jemalloc/jemalloc.c#l193
Reporter | ||
Updated•14 years ago
|
Hardware: x86_64 → All
Reporter | ||
Updated•14 years ago
|
Summary: Freeing large chunks of malloc'ed memory (e.g. decoded images) doesn't reduce memory usage → Freeing large chunks of malloc'ed memory (e.g. decoded images) doesn't reduce memory usage on Linux
Reporter | ||
Comment 15•14 years ago
|
||
I just built on Linux with #MALLOC_DECOMMIT defined, and it didn't fix the problem.
Reporter | ||
Comment 16•14 years ago
|
||
Moving this back to imagelib. I wrote a testcase which allocates a large arraybuffer in JS and then frees it and makes sure that freeing reduces RSS. This test passes on Linux, indicating to me that the problem isn't with jemalloc.
I'll attach the testcase in a moment.
Component: jemalloc → ImageLib
QA Contact: jemalloc → imagelib
Summary: Freeing large chunks of malloc'ed memory (e.g. decoded images) doesn't reduce memory usage on Linux → Freeing decoded images doesn't reduce memory usage on Linux
Reporter | ||
Comment 17•14 years ago
|
||
For kicks, I also ran the testcase on Mac with jemalloc; it passes there, too.
Reporter | ||
Comment 18•14 years ago
|
||
If we believe the RSS numbers in this about:memory dump, the decoded image data is never stored in the process's memory at all.
This is corroborated by instrumenting malloc -- I see a 170mb block malloc'ed and almost immediately free'd, even while the image is still onscreen. The free happens in imgFrame::Optimize.
Reporter | ||
Comment 19•14 years ago
|
||
That last attachment was an encoding fail; this one should work.
Attachment #540544 -
Attachment is obsolete: true
Reporter | ||
Updated•14 years ago
|
Attachment #540547 -
Attachment mime type: text/x-patch → text/plain
Comment 20•14 years ago
|
||
(In reply to comment #17)
> For kicks, I also ran the testcase on Mac with jemalloc; it passes there,
> too.
Thanks! Is that using the patch from bug 414946?
Reporter | ||
Comment 21•14 years ago
|
||
(In reply to comment #20)
> Thanks! Is that using the patch from bug 414946?
Yep! Worked great.
Reporter | ||
Comment 22•14 years ago
|
||
I think this is INVALID, per comment 18.
On Linux, about:memory shouldn't be reporting that the decoded images are stored on the heap -- this is bug 664659. Maybe we should also be reporting in about:memory how much space we're using inside the X server to store these images. I'll file a bug on that.
Status: NEW → RESOLVED
Closed: 14 years ago
Resolution: --- → INVALID
Reporter | ||
Comment 23•14 years ago
|
||
Filed bug 665952 on reporting the memory we're using in X.
You need to log in
before you can comment on or make changes to this bug.
Description
•