Closed Bug 989373 Opened 11 years ago Closed 7 years ago

Remove global reuse machinery in mozJSComponentLoader

Categories

(Core :: XPConnect, defect)

x86
macOS
defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla55
Tracking Status
firefox55 --- fixed

People

(Reporter: bholley, Assigned: mccr8)

References

(Blocks 1 open bug)

Details

Attachments

(8 files, 3 obsolete files)

(deleted), text/x-review-board-request
kmag
: review+
Details
(deleted), text/x-review-board-request
shu
: review+
Details
(deleted), text/x-review-board-request
kmag
: review+
Details
(deleted), text/x-review-board-request
kmag
: review+
Details
(deleted), text/x-review-board-request
kmag
: review+
Details
(deleted), text/x-review-board-request
kmag
: review+
Details
(deleted), text/x-review-board-request
kmag
: review+
Details
(deleted), text/x-review-board-request
kmag
: review+
Details
This was added by bug 798491 and its dependencies. It was a huge win. But it's also a pretty awful hack. It requires JS modules to follow very careful conventions with respect to the global, and causes them to break in unpredictable ways when they don't. Moreover, the code that implements it is super-complicated and buggy (see bug 980537 comment 28). Since then, we've introduced zones, which should give us most of the memory wins here. Extrapolating njn's findings in [1], all of the compartments in Gecko (system and non-system) impose a .4% overhead. This overhead should be further mitigated on b2g by Nuwa. The first thing I'd like to do is try switching off global sharing (jsloader.reuseGlobal) on b2g and see what the actual memory impact is. Given that AWSY doesn't do b2g, this probably requires manual measurements. njn, is this something you can measure easily? [1] https://groups.google.com/forum/#!msg/mozilla.dev.platform/sAuhWQOAWic/6p8uk1Bjo2AJ.
Blocks: 988880
Flags: needinfo?(n.nethercote)
I can try this once I get home from the JS work week. I just have to flip jsloader.reuseGlobal in b2g/app/b2g.js, right?
Flags: needinfo?(n.nethercote)
(In reply to Nicholas Nethercote [:njn] from comment #1) > I can try this once I get home from the JS work week. Awesome! Thank you very much. > I just have to flip jsloader.reuseGlobal in b2g/app/b2g.js, right? Correct. I'm going to leave you as ni? here just to make that that's the next step.
Flags: needinfo?(n.nethercote)
No longer blocks: 988880
(In reply to Nicholas Nethercote [:njn] from comment #1) > I can try this once I get home from the JS work week. > > I just have to flip jsloader.reuseGlobal in b2g/app/b2g.js, right? Unfortunately, it isn't that simple if you are testing on b2g, because of this hack: http://mxr.mozilla.org/mozilla-central/source/js/xpconnect/loader/mozJSComponentLoader.cpp#352 Frow what I know, you need to toggle the pref, and hack this code.
Whoa, nasty. Thanks for pointing that out, ochameau.
I've done the measurements on a trunk build on my Buri. I took them by rebooting the phone, waiting 30 seconds after the unlock screen first displayed, and then running get_about_memory.py. Overall, de-merging causes a ~20 MiB increase. I'll post a more detailed analysis soon. ----------------------------------------------------------------------------- merged system compartments ----------------------------------------------------------------------------- | megabytes | NAME PID NICE USS PSS RSS VSIZE OOM_ADJ USER b2g 146 0 49.1 55.0 67.8 166.9 0 root 352 0 2.5 7.7 20.3 52.9 0 root Homescreen 380 1 12.6 17.1 30.7 126.4 2 app_380 Built-in Keyboa 489 18 7.0 10.8 23.7 72.8 10 app_489 (Preallocated a 506 18 5.1 8.5 20.4 58.9 1 app_506 System memory info: Total 180.4 MB Used - cache 94.5 MB B2G procs (PSS) 99.0 MB Non-B2G procs -4.5 MB Free + cache 85.9 MB Free 31.5 MB Cache 54.4 MB ----------------------------------------------------------------------------- de-merged system compartments ----------------------------------------------------------------------------- | megabytes | NAME PID NICE USS PSS RSS VSIZE OOM_ADJ USER b2g 141 0 63.3 69.1 81.7 173.7 0 root 352 0 3.0 8.1 20.7 52.9 0 root Homescreen 381 1 15.4 19.8 33.4 124.0 2 app_381 Built-in Keyboa 530 18 8.7 12.4 25.3 73.8 10 app_530 (Preallocated a 547 18 7.0 10.3 22.2 60.9 1 app_547 System memory info: Total 180.4 MB Used - cache 114.6 MB B2G procs (PSS) 119.8 MB Non-B2G procs -5.3 MB Free + cache 65.9 MB Free 10.8 MB Cache 55.0 MB
Flags: needinfo?(n.nethercote)
I'll start with the main process because it shows the biggest increase. The number of system compartments increased from 8 to 151, so the change appears to have worked as intended. Here's the overall increase: > 15.10 MB (100.0%) -- explicit > ... > 14.40 MB ── resident The expected things (shape compartments and CCWs) were present, but only a small fraction. > │ │ ├──1.21 MB (08.64%) ── compartment-tables > ... > │ │ │ ├──0.45 MB (03.19%) ── cross-compartment-wrapper > ... > │ ├──0.63 MB (04.45%) ── cross-compartment-wrapper-table A lot of the increase was just objects. I don't understand this, particularly the presence of no property-iterator-data when compartments are merged and 0.31 MiB when the are de-merged. Could per-compartment GC be having an effect? (Do we even have per-compartment GC?) > │ ├──5.00 MB (35.62%) -- objects > │ │ ├──2.88 MB (20.53%) -- gc-heap > │ │ │ ├──1.25 MB (08.94%) ── function > │ │ │ ├──1.04 MB (07.42%) ── ordinary > │ │ │ ├──0.45 MB (03.19%) ── cross-compartment-wrapper > │ │ │ └──0.14 MB (00.98%) ── dense-array > │ │ └──2.12 MB (15.10%) -- malloc-heap > │ │ ├──1.28 MB (09.12%) ── slots > │ │ ├──0.50 MB (03.58%) ── elements/non-asm.js > │ │ ├──0.31 MB (02.22%) ── property-iterator-data [+] > │ │ └──0.02 MB (00.17%) ── regexp-statics [+] Shapes were also up. 1.2 MiB was due to the compartment shape table, mentioned above. The rest of the increase is presumably because shapes correlate closely to objects. > │ ├──3.41 MB (24.31%) -- shapes There were a couple of big images-as-data-URIs where we went from having 7 copies to 24 copies. I don't understand why. > │ │ │ ├──1.41 MB (09.31%) ++ string(length=28946, copies=24, "data:image/png;base64,iVBORw0KGgoA... > │ │ │ ├──0.84 MB (05.59%) ++ string(length=17210, copies=24, "data:image/png;base64,iVBORw0KGgoA... > │ │ │ ├──-0.41 MB (-2.72%) ++ string(length=28946, copies=7, "data:image/png;base64,iVBORw0KG... > │ │ │ ├──-0.25 MB (-1.63%) ++ string(length=17210, copies=7, "data:image/png;base64,iVBORw0KG... The amount of generated code was up quite a bit. A lot of it is unused. This might be because the minimum chunk size for JITted code is 64 KiB, so if they're not being shared, that's a problem. (The 64 KiB number is due to constraints that come from Windows; we could use 4 KiB on Linux, if that would help.) > │ ├───1.47 MB (09.72%) -- runtime > │ │ ├──1.44 MB (09.52%) -- code > │ │ │ ├──0.88 MB (05.80%) ── unused > │ │ │ ├──0.55 MB (03.67%) ── baseline > │ │ │ └──0.01 MB (00.05%) ++ (3 tiny) heap-overhead went *down*. No idea why: > ├──-2.43 MB (-16.10%) ++ heap-overhead The startup cache went from 0.05 to 1.23 MiB. I don't know if that is meaningful. Possibly not, though it shows that the startup cache can be a non-trivial amount of memory, perhaps, and system merging mostly affects JS. > ├──1.23 MB (08.16%) ── startup-cache/mapping heap-unclassified was up, which is a bit odd since the JS memory reporter coverage is very good. > ├──1.20 MB (07.97%) ── heap-unclassified xpconnect was a bit bigger: > ├──0.93 MB (06.18%) -- xpconnect > │ ├──0.79 MB (05.20%) ── scopes > │ └──0.15 MB (00.98%) -- (3 tiny) > │ ├──0.10 MB (00.66%) ── proto-iface-cache > │ ├──0.05 MB (00.35%) ── runtime > │ └──-0.00 MB (-0.03%) ── js-component-loader In the other processes, objects and shapes account for most of the difference.
How consistent is the effect? If you measure multiple times, do you see the same overall trends?
I just did two more runs with de-merging on. The first was quite a bit better (though still much worse than with merging), the second was similar to the original de-merging run. NAME PID NICE USS PSS RSS VSIZE OOM_ADJ USER b2g 141 0 63.3 69.1 81.7 173.7 0 root b2g 141 0 56.5 62.3 74.9 172.2 0 root b2g 141 0 64.4 70.2 82.8 180.2 0 root
Thanks a ton for diving into this Nick! Thoughts below. (In reply to Nicholas Nethercote [:njn] from comment #8) > The expected things (shape compartments and CCWs) were present, but only a > small fraction. That's kind of heartening, actually. It means that there might be some wins in here. > A lot of the increase was just objects. I don't understand this, particularly > the presence of no property-iterator-data when compartments are merged and > 0.31 > MiB when the are de-merged. Yeah, this seems like the big thing to investigate. One thing I can think of is that we'll end up having more XPCWNs, because those are per-compartment (so singletons like the observer service, which share 1 XPCWN in the merged world, get N XPCWNs in the unmerged world). But we really shouldn't have all that many of them floating around. > There were a couple of big images-as-data-URIs where we went from having 7 > copies to 24 copies. I don't understand why. That's concerning. With zones, string should be shared. We should definitely investigate this. > > > │ │ │ ├──1.41 MB (09.31%) ++ string(length=28946, copies=24, "data:image/png;base64,iVBORw0KGgoA... > > │ │ │ ├──0.84 MB (05.59%) ++ string(length=17210, copies=24, "data:image/png;base64,iVBORw0KGgoA... > > │ │ │ ├──-0.41 MB (-2.72%) ++ string(length=28946, copies=7, "data:image/png;base64,iVBORw0KG... > > │ │ │ ├──-0.25 MB (-1.63%) ++ string(length=17210, copies=7, "data:image/png;base64,iVBORw0KG... > > The amount of generated code was up quite a bit. A lot of it is unused. This > might be because the minimum chunk size for JITted code is 64 KiB, so if > they're not being shared, that's a problem. Yeah, it seems like we should look into this. > heap-overhead went *down*. No idea why: > > > ├──-2.43 MB (-16.10%) ++ heap-overhead It looks like this mostly relates to "waste". What is that? Fragmentation? > The startup cache went from 0.05 to 1.23 MiB. I don't know if that is > meaningful. Possibly not, though it shows that the startup cache can be a > non-trivial amount of memory, perhaps, and system merging mostly affects JS. > > > ├──1.23 MB (08.16%) ── startup-cache/mapping This is because, per bug 988880 comment 0, the startup cache is disabled for anything in the merged compartment. This seems to indicate that this consists of the majority of the startup cache's contents, so that supports my hypothesis that we should disable the startup cache entirely on b2g. > heap-unclassified was up, which is a bit odd since the JS memory reporter > coverage is very good. > > > ├──1.20 MB (07.97%) ── heap-unclassified Yeah. Might this correspond with the heap-overhead decrease? (though that was lower) > xpconnect was a bit bigger: Yeah, I think the per-compartment state here is unavoidable. But I'm surprised it's so high - effectively something a bit under 10k per scope. We should look into this - I don't know of anything there that should be using this much. Though this might be related to the object increase we're seeing. > In the other processes, objects and shapes account for most of the > difference. Ok, it sounds like that's really what we need to be investigating, then. Regardless of what we do for b2g compartments, there may be wins to be had on Desktop. Do you have more cycles to investigate this stuff Nick?
Depends on: 988880
> > heap-overhead went *down*. No idea why: > > > > > ├──-2.43 MB (-16.10%) ++ heap-overhead > > It looks like this mostly relates to "waste". What is that? Fragmentation? I don't understand exactly what it is, but it's some kind of jemalloc fragmentation and/or overhead. > Ok, it sounds like that's really what we need to be investigating, then. > Regardless of what we do for b2g compartments, there may be wins to be had > on Desktop. Do you have more cycles to investigate this stuff Nick? Potentially yes, but I'm unsure how to proceed.
(In reply to Nicholas Nethercote [:njn] from comment #12) > Potentially yes, but I'm unsure how to proceed. Well, investigating the open questions from comment 11 would be a start. Or are you unsure of how to go about that? I don't really know much about the b2g debugging story. Maybe we could reproduce it in a B2G Desktop build?
I instrumented the JS engine so that, on every object allocation, it prints the current JS location. I then did a b2g-desktop start-up with and without system compartment merging. With merging on, 156,825 objects are created. With it off, 219592 are created. I diff'd the two lists, and the diff is attached. I'll list some of the most common ones and include the relevant code snippets. I'll add arrows to indicate which line is the one doing the allocating, because it's not always obvious. I have commentary on a few of them, but there's lots of stuff going on here that I don't understand. ---- > ( 1) 8943 (12.8%, 12.8%): +obj: <internal> That's an allocation triggered from C++ code, and I don't have any insight into them right now. (I could get some, with effort, using Valgrind.) ---- > ( 2) 2448 ( 3.5%, 16.3%): +obj: resource://gre/modules/DOMRequestHelper.jsm, 95 > ( 3) 2448 ( 3.5%, 19.8%): +obj: resource://gre/modules/DOMRequestHelper.jsm, 179 These two are very similar. Here's the code for the second one, which is slightly simpler. Object.keys(this._listeners).forEach((aName) => { --> this._listeners[aName] ? cpmm.removeWeakMessageListener(aName, this) : cpmm.removeMessageListener(aName, this); delete this._listeners[aName]; }); Are we adding listeners at the compartment level? ---- > ( 4) 1727 ( 2.5%, 22.3%): +obj: resource://gre/modules/Webapps.jsm, 3372 doGetAll: function(aData, aMm) { this.getAll(function (apps) { aData.apps = apps; --> aMm.sendAsyncMessage("Webapps:GetAll:Return:OK", aData); }); }, I guess this is some kind of inter-compartment message which causes an object allocation? ---- > ( 5) 1269 ( 1.8%, 24.1%): +obj: self-hosted, 389 > ( 9) 511 ( 0.7%, 28.5%): +obj: self-hosted, 645 I have no insight into the allocations done by self-hosted code. ---- > ( 6) 1010 ( 1.4%, 25.6%): +obj: resource://gre/modules/XPCOMUtils.jsm, 226 defineLazyModuleGetter: function XPCU_defineLazyModuleGetter(aObject, aName, aResource, aSymbol) { this.defineLazyGetter(aObject, aName, function XPCU_moduleLambda() { var temp = {}; --> Cu.import(aResource, temp); return temp[aSymbol || aName]; }); }, ---- > ( 7) 828 ( 1.2%, 26.8%): +obj: file:///home/njn/moz/mi1/bo64/dist/bin/components/Webapps.js, 310 function createApplicationObject(aWindow, aApp) { let app = Cc["@mozilla.org/webapps/application;1"].createInstance(Ci.mozIDOMApplication); <-- app.wrappedJSObject.init(aWindow, aApp); return app; } ---- > ( 8) 665 ( 1.0%, 27.7%): +obj: resource://gre/modules/SystemMessagePermissionsChecker.jsm, 182 debug("isSystemMessagePermittedToRegister(): " + "aSysMsgName: " + aSysMsgName + ", " + "aOrigin: " + aOrigin + ", " + "aManifest: " + JSON.stringify(aManifest)); I don't even know how that allocates an object. ---- > (10) 492 ( 0.7%, 29.2%): +obj: resource://gre/modules/DOMRequestHelper.jsm, 175 > (12) 420 ( 0.6%, 30.4%): +obj: resource://gre/modules/DOMRequestHelper.jsm, 165 Services.obs.removeObserver(this, "inner-window-destroyed"); and Services.obs.addObserver(this, "inner-window-destroyed", /* weak-ref */ true); ---- > (11) 443 ( 0.6%, 29.8%): +obj: resource://gre/modules/Webapps.jsm, 3597 > (15) 358 ( 0.5%, 32.0%): +obj: resource://gre/modules/Webapps.jsm, 3611 Multiple similar ones. Here's the code for one of them. getAppByManifestURL: function(aManifestURL) { -> return AppsUtils.getAppByManifestURL(this.webapps, aManifestURL); }, ---- > (13) 410 ( 0.6%, 31.0%): +obj: file:///home/njn/moz/mi1/bo64/dist/bin/components/Webapps.js, 24 function convertAppsArray(aApps, aWindow) { let apps = new aWindow.Array(); for (let i = 0; i < aApps.length; i++) { let app = aApps[i]; -> apps.push(createApplicationObject(aWindow, app)); } ---- > (14) 358 ( 0.5%, 31.5%): +obj: file:///home/njn/moz/mi1/bo64/dist/bin/components/AppsService.js, 54 getAppByLocalId: function getAppByLocalId(aLocalId) { debug("getAppByLocalId( " + aLocalId + " )"); -> return DOMApplicationRegistry.getAppByLocalId(aLocalId); }, ---- > (16) 330 ( 0.5%, 32.5%): +obj: resource://gre/modules/commonjs/sdk/core/promise.js, 10 this.console = this['Components'].utils .import('resource://gre/modules/devtools/Console.jsm', {}).console; ---- > (17) 310 ( 0.4%, 32.9%): +obj: resource://gre/modules/XPCOMUtils.jsm, 180 defineLazyGetter: function XPCU_defineLazyGetter(aObject, aName, aLambda) { Object.defineProperty(aObject, aName, { get: function () { delete aObject[aName]; return aObject[aName] = aLambda.apply(aObject); }, configurable: true, enumerable: true }); }, ---- > (18) 301 ( 0.4%, 33.4%): -obj: resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/touch-events.js, 66 --> if (evt.button || evt.mozInputSource != Ci.nsIDOMMouseEvent.MOZ_SOURCE_MOU SE || evt.isSynthesized) { return; } Again, is that an object allocation? ---- > (19) 296 ( 0.4%, 33.8%): +obj: resource://gre/modules/XPCOMUtils.jsm, 110 generateQI: function XPCU_generateQI(interfaces) { /* Note that Ci[Ci.x] == Ci.x for all x */ -> return makeQI([Ci[i].name for each (i in interfaces) if (Ci[i])]); }, ---- > (20) 276 ( 0.4%, 34.2%): +obj: resource://gre/modules/Task.jsm, 334 aValue.then(this._run.bind(this, true), this._run.bind(this, false)); ---- If I had to summarize, I'd say something about importing modules, sending messages, and adding/removing observers. Which all sounds broadly plausible, but I don't have the first idea about how to improve it.
> > ( 2) 2448 ( 3.5%, 16.3%): +obj: resource://gre/modules/DOMRequestHelper.jsm, 95 > > ( 3) 2448 ( 3.5%, 19.8%): +obj: resource://gre/modules/DOMRequestHelper.jsm, 179 I looked at this one more closely, using dump() to instrument. Each of these lines is executed 1224 times when 'weak' is true. With merging enabled, each execution triggers two object allocations. With merging disabled, each execution triggers four object allocations. I don't know how to interpret this, because I can't see how any objects are allocated for these cases.
One factor is that global objects are big: http://dxr.mozilla.org/mozilla-central/source/js/src/vm/GlobalObject.h#38-68 They typically have ~150 slots, which is over 1200 bytes. And some of those slots hold objects (e.g. RegExpStatics). There might be related shape info too.
Depends on: 997906
Hi Bobby, I'm trying to enable the SafeBrowsing feature on Firefox OS ( bug #839120 ). Although, I'm facing the issue that it can't be loaded JS module. > var jslib = Cc["@mozilla.org/url-classifier/jslib;1"] > .getService().wrappedJSObject; in that code on Firefox OS, jslib object has [object FakeBackStagePass]. But, in Firefox Browser, jslib object [object BackStagePass]. If it was built with 'jsloader.reuseGlobal' = false, jslib object has [object BackStagePass] on Firefox OS. But, in Firefox OS, that prefs has false with default. Then, I'd like to know how to load JS module on Firefox OS. If you wouldn't mind, could you suggest me what should I code?
Flags: needinfo?(bobbyholley)
(In reply to Yusuke Yamamoto from comment #17) > Hi Bobby, > > I'm trying to enable the SafeBrowsing feature on Firefox OS ( bug #839120 ). > Although, I'm facing the issue that it can't be loaded JS module. > > > var jslib = Cc["@mozilla.org/url-classifier/jslib;1"] > > .getService().wrappedJSObject; > > in that code on Firefox OS, jslib object has [object FakeBackStagePass]. > But, in Firefox Browser, jslib object [object BackStagePass]. Right, because on b2g, all of these components live in the same global, and have separate scope objects of type FakeBackStagePass. > Then, I'd like to know how to load JS module on Firefox OS. > If you wouldn't mind, could you suggest me what should I code? If you want this code to work properly on b2g, you'll need to make sure that all the code included at [1] properly handles the case where this != global. See all of the changes made in the massive patch in bug 798491. [1] http://mxr.mozilla.org/mozilla-central/source/toolkit/components/url-classifier/nsUrlClassifierLib.js#15
Flags: needinfo?(bobbyholley)
(In reply to Bobby Holley (:bholley) from comment #18) > If you want this code to work properly on b2g, you'll need to make sure that > all the code included at [1] properly handles the case where this != global. > See all of the changes made in the massive patch in bug 798491. > > [1] > http://mxr.mozilla.org/mozilla-central/source/toolkit/components/url- > classifier/nsUrlClassifierLib.js#15 Thank you Bobby, but actuary, I wouldn't get the detail. Could you elaborate on that?
Flags: needinfo?(bobbyholley)
(In reply to Yusuke Yamamoto from comment #19) > Thank you Bobby, > but actuary, I wouldn't get the detail. > Could you elaborate on that? On b2g, we have a hack whereby all (or many) of the system JS components share a single global. This saves a bunch of memory, but doesn't give the same level of isolation as having separate globals. What we do is to evaluate each component with a different scope object, which makes them behave roughly as though they were evaluated in the body of an anonymous |function() { ... }|. The main impact of this is that, for code to work in this context, you need to explicitly qualify lookups with |this| so that they operate on the scope object (per component) and not the global (shared among all the components).
Flags: needinfo?(bobbyholley)
I redid the measurements because we now have per-class reporting in about:memory. I'll just discuss the b2g process, since that's the most important one. Overall, de-merging compartments still has a big cost: > 11,481,088 B (100.0%) -- explicit > 11,313,152 B ── resident But that's a bit lower than comment 8, where it was 15 MiB. (And I measured twice, with the other one having "resident" and "explicit" differences around 9.5 MiB.) In short, a lot of the object/shape difference with system compartments demerged is due to Function objects and BackstagePass objects. ---- Here's the high-level difference: > 11,481,088 B (100.0%) -- explicit > ├───5,776,000 B (50.31%) ++ js-non-window > ├───3,796,848 B (33.07%) ── startup-cache/data > ├───1,017,236 B (08.86%) -- heap-overhead > │ ├──1,232,820 B (10.74%) ── bin-unused > │ ├───-307,200 B (-2.68%) ── page-cache > │ └─────91,616 B (00.80%) ── bookkeeping > ├───────4,096 B (00.04%) ++ images/content/raster > ├─────564,876 B (04.92%) ── heap-unclassified > ├─────271,584 B (02.37%) -- xpconnect > │ ├──193,104 B (01.68%) ── scopes > │ ├───73,088 B (00.64%) ── proto-iface-cache > │ ├───10,432 B (00.09%) ── runtime > │ ├───-5,760 B (-0.05%) ── js-component-loader > │ └──────720 B (00.01%) ── wrappedjs > ├──────89,040 B (00.78%) -- dmd/stack-traces > │ ├──60,144 B (00.52%) ── unused > │ └──28,896 B (00.25%) ── used > ├─────-59,936 B (-0.52%) ++ window-objects > ├──────16,384 B (00.14%) ── cycle-collector/purple-buffer > ├───────3,312 B (00.03%) -- gfx > │ ├──2,048 B (00.02%) ── heap-textures > │ └──1,264 B (00.01%) ── font-shaped-words > ├───────1,168 B (00.01%) ── preferences > ├─────────512 B (00.00%) ── workers/workers(chrome)/worker(resource://gre/modules/ril_worker.js, 0xNNN)/zone(0xNNN)/compartment(web-worker)/classes/class(Object)/shapes/malloc-heap/tree-kids > └─────────-32 B (-0.00%) ── atom-tables/main A lot of this is broadly similar to comment 8: JS up a lot, startup-cache/data up a lot (more this time), heap-unclassified up, xpconnect up a bit. (BTW, the startup cache was disabled in bug 988880, and then bug 999631 fiddled with the disabling... it must have broken the disabling somehow.) Here's the high-level JS breakdown, without any class-specific measurements. > 5,724,224 B (100.0%) -- js-main-runtime > ├──4,726,744 B (82.57%) -- compartments > │ ├──3,566,984 B (62.31%) -- classes > │ │ ├──2,011,008 B (35.13%) -- objects > │ │ │ ├──1,237,072 B (21.61%) ── gc-heap > │ │ │ └────773,936 B (13.52%) -- malloc-heap > │ │ │ ├──766,784 B (13.40%) ── slots > │ │ │ ├────6,640 B (00.12%) ── misc > │ │ │ └──────512 B (00.01%) ── elements/non-asm.js > │ │ └──1,555,976 B (27.18%) -- shapes > │ │ ├──1,453,064 B (25.38%) -- gc-heap > │ │ │ ├──1,014,432 B (17.72%) ── tree > │ │ │ ├────228,864 B (04.00%) ── base > │ │ │ └────209,768 B (03.66%) ── dict > │ │ └────102,912 B (01.80%) -- malloc-heap > │ │ ├───74,992 B (01.31%) ── dict-tables > │ │ ├───52,976 B (00.93%) ── tree-kids > │ │ └──-25,056 B (-0.44%) ── tree-tables > │ ├────649,536 B (11.35%) ── compartment-tables > │ ├────188,672 B (03.30%) ── cross-compartment-wrapper-table > │ ├────123,080 B (02.15%) -- scripts > │ │ ├──111,744 B (01.95%) ── gc-heap > │ │ └───11,336 B (00.20%) ── malloc-heap/data > │ ├────116,168 B (02.03%) -- type-inference > │ │ ├───36,640 B (00.64%) ── array-type-tables > │ │ ├───36,256 B (00.63%) ── allocation-site-tables > │ │ ├───35,832 B (00.63%) ── object-type-tables > │ │ └────7,440 B (00.13%) ── type-scripts > │ ├─────65,664 B (01.15%) ── compartment-object > │ ├──────9,728 B (00.17%) ── regexp-compartment > │ └──────6,912 B (00.12%) -- baseline > │ ├──4,864 B (00.08%) ── fallback-stubs > │ └──2,048 B (00.04%) ── data > ├────448,840 B (07.84%) -- zones > │ ├──388,488 B (06.79%) ── unused-gc-things > │ ├──158,240 B (02.76%) ── type-objects/gc-heap > │ ├──-147,456 B (-2.58%) ── type-pool > │ ├───28,352 B (00.50%) -- strings > │ │ ├──21,664 B (00.38%) -- gc-heap > │ │ │ ├──20,864 B (00.36%) ── latin1 > │ │ │ └─────800 B (00.01%) ── two-byte > │ │ └───6,688 B (00.12%) ── malloc-heap/latin1 > │ ├───20,096 B (00.35%) ── gc-heap-arena-admin > │ └────1,120 B (00.02%) ── jit-codes-gc-heap > ├────417,568 B (07.29%) ── runtime > └────131,072 B (02.29%) ── gc-heap/chunk-admin CCWs again account for some, but it's mostly just a case of more objects and shapes. Here's the list of compartments and their sizes. We can see the big merged one (the -4,262,240 B one) and all the de-merged ones (the positive ones). The increase in compartment count is 152. The sizes vary greatly from almost 600 KiB down to 20 KiB (with a couple of weird ones being around 2 KiB). > │ ├──5,227,360 B (45.53%) -- zones/zone(0xNNN) > │ │ ├──-4,262,240 B (-37.12%) ++ compartment([System Principal]) > │ │ ├────594,544 B (05.18%) ++ compartment([System Principal], resource://gre/modules/AppsServiceChild.jsm) > │ │ ├────488,536 B (04.26%) ++ compartment([System Principal], resource://gre/modules/AppsUtils.jsm) > │ │ ├────429,992 B (03.75%) ── unused-gc-things [3] > │ │ ├────297,424 B (02.59%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/marionettecomponent.js) > │ │ ├────243,928 B (02.12%) ++ compartment([System Principal], resource://gre/modules/Webapps.jsm) > │ │ ├────212,288 B (01.85%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/RadioInterfaceLayer.js) > │ │ ├────211,072 B (01.84%) ++ compartment([System Principal], resource://gre/modules/ril_consts.js) > │ │ ├────210,536 B (01.83%) ++ compartment([System Principal], resource://gre/modules/XPCOMUtils.jsm) > │ │ ├────161,512 B (01.41%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/WifiWorker.js) > │ │ ├────158,304 B (01.38%) ++ type-objects > │ │ ├────149,496 B (01.30%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/MobileConnectionService.js) > │ │ ├───-147,456 B (-1.28%) ── type-pool [3] > │ │ ├────135,372 B (01.18%) ++ compartment([System Principal], resource://gre/modules/ctypes.jsm) > │ │ ├────125,224 B (01.09%) ++ compartment([System Principal], resource://gre/modules/MobileMessageDB.jsm) > │ │ ├────122,224 B (01.06%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/Webapps.js) > │ │ ├────121,400 B (01.06%) ++ compartment([System Principal], resource://gre/modules/MobileIdentityCommon.jsm) > │ │ ├────115,248 B (01.00%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/TelephonyService.js) > │ │ ├────112,400 B (00.98%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/SettingsManager.js) > │ │ ├────108,696 B (00.95%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/RILContentHelper.js) > │ │ ├────107,368 B (00.94%) ++ compartment([System Principal], resource://gre/modules/wap_consts.js) > │ │ ├────107,328 B (00.93%) ++ compartment([System Principal], resource://gre/modules/nfc_consts.js) > │ │ ├─────98,064 B (00.85%) ++ compartment([System Principal], resource://gre/modules/WspPduHelper.jsm) > │ │ ├─────97,336 B (00.85%) ++ compartment([System Principal], resource://gre/modules/commonjs/toolkit/loader.js) > │ │ ├─────93,616 B (00.82%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/CellBroadcastService.js) > │ │ ├─────92,432 B (00.81%) ++ compartment([System Principal], resource://gre/modules/SettingsRequestManager.jsm) > │ │ ├─────89,896 B (00.78%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/VoicemailService.js) > │ │ ├─────87,888 B (00.77%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/TelephonyAudioService.js) > │ │ ├─────86,176 B (00.75%) ++ compartment([System Principal], resource://gre/modules/ContactDB.jsm) > │ │ ├─────83,840 B (00.73%) ++ compartment([System Principal], resource://gre/modules/PushService.jsm) > │ │ ├─────75,984 B (00.66%) ++ compartment([System Principal], resource://gre/modules/NetworkStatsDB.jsm) > │ │ ├─────75,840 B (00.66%) ++ compartment([System Principal], resource://gre/modules/Log.jsm) > │ │ ├─────71,152 B (00.62%) ++ compartment([System Principal], resource://gre/modules/osfile/osfile_shared_allthreads.jsm) > │ │ ├─────67,976 B (00.59%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/NetworkManager.js) > │ │ ├─────67,784 B (00.59%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/DataStoreImpl.js) > │ │ ├─────67,400 B (00.59%) ++ compartment([System Principal], resource://gre/modules/WifiCommand.jsm) > │ │ ├─────66,664 B (00.58%) ++ compartment([System Principal], resource://gre/modules/TelemetryPing.jsm) > │ │ ├─────65,528 B (00.57%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/SystemMessageInternal.js) > │ │ ├─────65,312 B (00.57%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/NetworkService.js) > │ │ ├─────64,608 B (00.56%) ++ compartment([System Principal], resource://gre/modules/osfile/osfile_async_front.jsm) > │ │ ├─────62,936 B (00.55%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/BrowserElementParent.js) > │ │ ├─────61,368 B (00.53%) ++ compartment([System Principal], resource://gre/modules/NetworkStatsService.jsm) > │ │ ├─────59,616 B (00.52%) ++ compartment([System Principal], resource://gre/modules/IndexedDBHelper.jsm) > │ │ ├─────58,152 B (00.51%) ++ compartment([System Principal], resource://gre/modules/AsyncShutdown.jsm) > │ │ ├─────56,544 B (00.49%) ++ compartment([System Principal], resource://gre/modules/DownloadIntegration.jsm) > │ │ ├─────56,240 B (00.49%) ++ compartment([System Principal], resource://gre/modules/Promise.jsm) > │ │ ├─────55,112 B (00.48%) ++ compartment([System Principal], resource://gre/modules/ResourceStatsDB.jsm) > │ │ ├─────54,488 B (00.47%) ++ compartment([System Principal], resource://gre/modules/WifiP2pManager.jsm) > │ │ ├─────53,576 B (00.47%) ++ compartment([System Principal], resource://gre/modules/DOMRequestHelper.jsm) > │ │ ├─────53,360 B (00.46%) ++ compartment([System Principal], resource://gre/modules/DownloadCore.jsm) > │ │ ├─────53,104 B (00.46%) ++ compartment([System Principal], resource://gre/modules/DataStoreDB.jsm) > │ │ ├─────51,936 B (00.45%) ++ compartment([System Principal], resource://gre/modules/MobileIdentityManager.jsm) > │ │ ├─────50,672 B (00.44%) ++ compartment([System Principal], resource://gre/modules/SettingsDB.jsm) > │ │ ├─────49,484 B (00.43%) ++ compartment([System Principal], resource://gre/modules/Sntp.jsm) > │ │ ├─────47,656 B (00.42%) ++ compartment([System Principal], resource://gre/modules/UserAgentUpdates.jsm) > │ │ ├─────46,752 B (00.41%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/MozKeyboard.js) > │ │ ├─────46,496 B (00.40%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/DOMWifiManager.js) > │ │ ├─────46,208 B (00.40%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/nsUpdateTimerManager.js) > │ │ ├─────45,888 B (00.40%) ++ compartment([System Principal], resource://gre/modules/devtools/Loader.jsm) > │ │ ├─────45,552 B (00.40%) ++ compartment([System Principal], resource://gre/modules/devtools/Console.jsm) > │ │ ├─────44,840 B (00.39%) ++ compartment([System Principal], resource://gre/modules/CrashSubmit.jsm) > │ │ ├─────44,600 B (00.39%) ++ compartment([System Principal], resource://gre/modules/FxAccountsCommon.js) > │ │ ├─────44,376 B (00.39%) ++ compartment([System Principal], resource://gre/modules/InterAppCommService.jsm) > │ │ ├─────43,448 B (00.38%) ++ compartment([System Principal], resource://gre/modules/SystemMessagePermissionsChecker.jsm) > │ │ ├─────43,320 B (00.38%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/ContentPermissionPrompt.js) > │ │ ├─────43,264 B (00.38%) ++ compartment([System Principal], resource://gre/modules/Keyboard.jsm) > │ │ ├─────42,896 B (00.37%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/captivedetect.js) > │ │ ├─────42,424 B (00.37%) ++ compartment([System Principal], resource://gre/modules/Task.jsm) > │ │ ├─────42,224 B (00.37%) ++ compartment([System Principal], resource://gre/modules/DOMIdentity.jsm) > │ │ ├─────41,904 B (00.36%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/nsPrompter.js) > │ │ ├─────41,648 B (00.36%) ++ compartment([System Principal], resource://gre/modules/osfile/ospath_unix.jsm) > │ │ ├─────41,224 B (00.36%) ++ compartment([System Principal], resource://gre/modules/AlarmService.jsm) > │ │ ├─────41,056 B (00.36%) ++ compartment([System Principal], resource://gre/modules/PermissionsTable.jsm) > │ │ ├─────40,880 B (00.36%) ++ compartment([System Principal], resource://gre/modules/UserAgentOverrides.jsm) > │ │ ├─────39,496 B (00.34%) ++ compartment([System Principal], resource://gre/modules/DownloadList.jsm) > │ │ ├─────39,392 B (00.34%) ++ compartment([System Principal], resource://gre/modules/BrowserElementPromptService.jsm) > │ │ ├─────38,784 B (00.34%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/DownloadsAPI.js) > │ │ ├─────38,400 B (00.33%) ++ compartment([System Principal], resource://gre/modules/Services.jsm) > │ │ ├─────38,320 B (00.33%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/SettingsService.js) > │ │ ├─────38,000 B (00.33%) ++ compartment([System Principal], resource://gre/modules/OperatorApps.jsm) > │ │ ├─────37,864 B (00.33%) ++ compartment([System Principal], resource://gre/modules/osfile/osfile_unix_allthreads.jsm) > │ │ ├─────37,104 B (00.32%) ++ compartment([System Principal], resource://gre/modules/systemlibs.js) > │ │ ├─────36,864 B (00.32%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/ProcessGlobal.js) > │ │ ├─────36,384 B (00.32%) ++ compartment([System Principal], resource://gre/modules/NotificationDB.jsm) > │ │ ├─────35,168 B (00.31%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/InterAppMessagePort.js) > │ │ ├─────34,664 B (00.30%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/SystemMessageManager.js) > │ │ ├─────34,160 B (00.30%) ++ compartment([System Principal], resource://gre/modules/ActivitiesService.jsm) > │ │ ├─────34,128 B (00.30%) ++ compartment([System Principal], resource://gre/modules/Downloads.jsm) > │ │ ├─────34,112 B (00.30%) ++ compartment([System Principal], resource://gre/modules/AlertsHelper.jsm) > │ │ ├─────34,032 B (00.30%) ++ compartment([System Principal], resource://gre/modules/DownloadsAPI.jsm) > │ │ ├─────34,000 B (00.30%) ++ compartment([System Principal], resource://gre/modules/Geometry.jsm) > │ │ ├─────33,176 B (00.29%) ++ compartment([System Principal], resource://gre/modules/WifiNetUtil.jsm) > │ │ ├─────32,368 B (00.28%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/NotificationStorage.js) > │ │ ├─────31,496 B (00.27%) ++ compartment([System Principal], resource://gre/modules/PromiseWorker.jsm) > │ │ ├─────31,304 B (00.27%) ++ compartment([System Principal], resource://gre/modules/Payment.jsm) > │ │ ├─────30,616 B (00.27%) ++ compartment([System Principal], resource://gre/modules/DownloadStore.jsm) > │ │ ├─────30,536 B (00.27%) ++ compartment([System Principal], resource://gre/modules/ContactService.jsm) > │ │ ├─────30,472 B (00.27%) ++ compartment([System Principal], resource://gre/modules/WebappOSUtils.jsm) > │ │ ├─────30,384 B (00.26%) ++ compartment([System Principal], resource://gre/modules/NetUtil.jsm) > │ │ ├─────29,832 B (00.26%) ++ compartment([System Principal], [anonymous sandbox] (from: resource://gre/modules/devtools/Loader.jsm:55)) > │ │ ├─────29,632 B (00.26%) ++ compartment([System Principal], resource://gre/modules/DataStoreChangeNotifier.jsm) > │ │ ├─────29,592 B (00.26%) ++ compartment([System Principal], resource://gre/modules/Preferences.jsm) > │ │ ├─────29,544 B (00.26%) ++ compartment([System Principal], resource://gre/modules/WapPushManager.js) > │ │ ├─────29,496 B (00.26%) ++ compartment([System Principal], resource://gre/modules/ThirdPartyCookieProbe.jsm) > │ │ ├─────29,088 B (00.25%) ++ compartment([System Principal], resource://specialpowers/MockFilePicker.jsm) > │ │ ├─────29,064 B (00.25%) ++ compartment([System Principal], resource://gre/modules/DataStoreCursorImpl.jsm) > │ │ ├─────29,008 B (00.25%) ++ compartment([System Principal], resource://gre/modules/AlarmDB.jsm) > │ │ ├─────29,008 B (00.25%) ++ compartment([System Principal], resource://gre/modules/FxAccountsMgmtService.jsm) > │ │ ├─────28,816 B (00.25%) ++ compartment([System Principal], resource://gre/modules/PhoneNumberUtils.jsm) > │ │ ├─────28,448 B (00.25%) ++ strings > │ │ ├─────28,424 B (00.25%) ++ compartment([System Principal], resource://gre/modules/DownloadsIPC.jsm) > │ │ ├─────28,232 B (00.25%) ++ compartment([System Principal], resource://gre/modules/FileUtils.jsm) > │ │ ├─────27,800 B (00.24%) ++ compartment([System Principal], resource://gre/modules/SignInToWebsite.jsm) > │ │ ├─────27,376 B (00.24%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/DirectoryProvider.js) > │ │ ├─────27,344 B (00.24%) ++ compartment([System Principal], resource://gre/modules/osfile/osfile_native.jsm) > │ │ ├─────27,312 B (00.24%) ++ compartment([System Principal], resource://gre/modules/WifiP2pWorkerObserver.jsm) > │ │ ├─────27,248 B (00.24%) ++ compartment([System Principal], resource://gre/modules/mcc_iso3166_table.jsm) > │ │ ├─────27,160 B (00.24%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/AppsService.js) > │ │ ├─────27,128 B (00.24%) ++ compartment([System Principal], resource://gre/modules/ResourceStatsService.jsm) > │ │ ├─────26,904 B (00.23%) ++ compartment([System Principal], resource://gre/modules/ErrorPage.jsm) > │ │ ├─────26,192 B (00.23%) ++ compartment([System Principal], chrome://marionette/content/marionette-elements.js) > │ │ ├─────25,416 B (00.22%) ++ compartment([System Principal], resource://gre/modules/PermissionsInstaller.jsm) > │ │ ├─────25,400 B (00.22%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/MobileMessageDatabaseService.js) > │ │ ├─────25,160 B (00.22%) ++ compartment([System Principal], resource://gre/modules/DownloadUIHelper.jsm) > │ │ ├─────25,064 B (00.22%) ++ compartment([System Principal], resource://gre/modules/DeferredTask.jsm) > │ │ ├─────24,784 B (00.22%) ++ compartment([System Principal], resource://specialpowers/MockPermissionPrompt.jsm) > │ │ ├─────24,656 B (00.21%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/InterAppConnection.js) > │ │ ├─────24,624 B (00.21%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/EngineeringModeService.js) > │ │ ├─────24,624 B (00.21%) ++ compartment([System Principal], resource://specialpowers/MockColorPicker.jsm) > │ │ ├─────24,576 B (00.21%) ++ compartment([System Principal], resource://gre/modules/PermissionSettings.jsm) > │ │ ├─────24,416 B (00.21%) ++ compartment([System Principal], resource://gre/modules/StateMachine.jsm) > │ │ ├─────24,336 B (00.21%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/ConsoleAPIStorage.js) > │ │ ├─────24,232 B (00.21%) ++ compartment([System Principal], resource://gre/modules/KeyValueParser.jsm) > │ │ ├─────24,000 B (00.21%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/ChromeNotifications.js) > │ │ ├─────23,784 B (00.21%) ++ compartment([System Principal], resource://gre/modules/PrivateBrowsingUtils.jsm) > │ │ ├─────23,728 B (00.21%) ++ compartment([System Principal], resource://gre/modules/SystemAppProxy.jsm) > │ │ ├─────23,232 B (00.20%) ++ compartment([System Principal], resource://gre/modules/Timer.jsm) > │ │ ├─────22,936 B (00.20%) ++ compartment([System Principal], resource://gre/modules/WebappsUpdater.jsm) > │ │ ├─────22,928 B (00.20%) ++ compartment([System Principal], resource://gre/modules/TelemetryStopwatch.jsm) > │ │ ├─────22,808 B (00.20%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/InterAppCommUIGlue.js) > │ │ ├─────22,680 B (00.20%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/messageWakeupService.js) > │ │ ├─────22,568 B (00.20%) ++ compartment([System Principal], resource://gre/modules/identity/LogUtils.jsm) > │ │ ├─────22,512 B (00.20%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/FormAutofillStartup.js) > │ │ ├─────22,424 B (00.20%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/FormHistoryStartup.js) > │ │ ├─────22,264 B (00.19%) ++ compartment([System Principal], resource://gre/modules/AppDownloadManager.jsm) > │ │ ├─────22,136 B (00.19%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/nsDefaultCLH.js) > │ │ ├─────21,904 B (00.19%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/InterAppCommService.js) > │ │ ├─────21,200 B (00.18%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/PushServiceLauncher.js) > │ │ ├─────21,184 B (00.18%) ++ compartment([System Principal], resource://gre/modules/SharedPromptUtils.jsm) > │ │ ├─────21,176 B (00.18%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/nsIDService.js) > │ │ ├─────20,568 B (00.18%) ++ compartment([System Principal], resource://gre/modules/osfile/ospath.jsm) > │ │ ├─────20,368 B (00.18%) ── gc-heap-arena-admin [3] > │ │ ├─────20,304 B (00.18%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/jsconsole-clhandler.js) > │ │ ├─────20,160 B (00.18%) ++ compartment([System Principal], jar:file:///system/b2g/omni.ja!/components/TelemetryStartup.js) > │ │ ├─────19,824 B (00.17%) ++ compartment([System Principal], resource://gre/modules/MobileIdentityUIGlueCommon.jsm) > │ │ ├─────19,600 B (00.17%) ++ compartment([System Principal], resource://gre/modules/jsdebugger.jsm) > │ │ ├─────19,504 B (00.17%) ++ compartment([System Principal], resource://gre/modules/reflect.jsm) > │ │ ├─────19,424 B (00.17%) ++ compartment([System Principal], resource://gre/modules/debug.js) > │ │ ├─────19,128 B (00.17%) ++ compartment([System Principal], resource://gre/modules/osfile.jsm) > │ │ ├─────-2,832 B (-0.02%) ++ compartment([System Principal], Addon-SDK (from: resource://gre/modules/commonjs/toolkit/loader.js:237)) > │ │ ├──────1,984 B (00.02%) ++ compartment([System Principal], inProcessTabChildGlobal?ownedBy=chrome://b2g/content/shell.html) > │ │ ├──────1,120 B (00.01%) ── jit-codes-gc-heap [3] > │ │ └───────-352 B (-0.00%) ++ compartment(moz-nullprincipal:{NNNNNNNN-NNNN-NNNN-NNNN-NNNNNNNNNNNN}, XPConnect Junk Compartment)/classes/class(Object)/objects Here is the big, merged compartment in detail. (I dialed down several of the JS memory reporter's significance thresholds in order to get more class-specific detail than normal.) > ├──-4,262,240 B (-37.12%) -- compartment([System Principal]) > │ ├──-2,970,932 B (-25.88%) -- classes > │ │ ├──-1,692,904 B (-14.75%) -- class(Object) > │ │ │ ├──-1,018,976 B (-8.88%) ++ objects > │ │ │ └────-673,928 B (-5.87%) ++ shapes > │ │ ├────-454,760 B (-3.96%) -- class(Function) > │ │ │ ├──-406,496 B (-3.54%) ++ objects > │ │ │ └───-48,264 B (-0.42%) ++ shapes > │ │ ├────-170,368 B (-1.48%) -- class(Call) > │ │ │ ├───-95,872 B (-0.84%) ++ shapes > │ │ │ └───-74,496 B (-0.65%) ++ objects > │ │ ├────-139,488 B (-1.21%) -- class(Array) > │ │ │ ├──-137,584 B (-1.20%) ++ objects > │ │ │ └────-1,904 B (-0.02%) ++ shapes > │ │ ├────-137,488 B (-1.20%) -- class(FakeBackstagePass) > │ │ │ ├──-100,560 B (-0.88%) ++ shapes > │ │ │ └───-36,928 B (-0.32%) ++ objects > │ │ ├────-127,416 B (-1.11%) -- class(Block) > │ │ │ ├───-84,960 B (-0.74%) ++ objects > │ │ │ └───-42,456 B (-0.37%) ++ shapes > │ │ ├─────-87,736 B (-0.76%) -- class(nsXPCComponents_Interfaces) > │ │ │ ├──-85,656 B (-0.75%) ++ shapes > │ │ │ └───-2,080 B (-0.02%) ++ objects > │ │ ├─────-25,200 B (-0.22%) -- class(XPCWrappedNative_NoHelper) > │ │ │ ├──-17,664 B (-0.15%) ++ objects > │ │ │ └───-7,536 B (-0.07%) ++ shapes > │ │ ├─────-15,912 B (-0.14%) -- class(Proxy) > │ │ │ ├──-15,856 B (-0.14%) ── objects/gc-heap > │ │ │ └──────-56 B (-0.00%) ++ shapes/gc-heap > │ │ ├─────-13,624 B (-0.12%) -- class(nsXPCComponents_Classes) > │ │ │ ├──-12,568 B (-0.11%) ++ shapes > │ │ │ └───-1,056 B (-0.01%) ++ objects > │ │ ├─────-11,552 B (-0.10%) -- class(With) > │ │ │ ├───-7,680 B (-0.07%) ── objects/gc-heap > │ │ │ └───-3,872 B (-0.03%) ++ shapes/gc-heap > │ │ ├──────-9,328 B (-0.08%) -- class(CType) > │ │ │ ├──-8,288 B (-0.07%) ++ objects > │ │ │ └──-1,040 B (-0.01%) ++ shapes > │ │ ├──────-9,288 B (-0.08%) -- class(nsJSIID) > │ │ │ ├──-6,624 B (-0.06%) ++ objects > │ │ │ └──-2,664 B (-0.02%) ++ shapes > │ │ ├──────-8,052 B (-0.07%) -- class(CData) > │ │ │ ├──-6,588 B (-0.06%) ++ objects > │ │ │ └──-1,464 B (-0.01%) ++ shapes > │ │ ├──────-7,928 B (-0.07%) -- class(ScriptSource) > │ │ │ ├──-7,872 B (-0.07%) ── objects/gc-heap > │ │ │ └─────-56 B (-0.00%) ++ shapes/gc-heap > │ │ ├──────-6,512 B (-0.06%) -- class(RegExp) > │ │ │ ├──-5,744 B (-0.05%) ++ objects > │ │ │ └────-768 B (-0.01%) ++ shapes > │ │ ├──────-5,176 B (-0.05%) -- class(WithTemplate) > │ │ │ ├──-5,120 B (-0.04%) ── objects/gc-heap > │ │ │ └─────-56 B (-0.00%) ++ shapes/gc-heap > │ │ ├──────-4,936 B (-0.04%) -- class(BackstagePass) > │ │ │ ├──-2,744 B (-0.02%) ++ shapes > │ │ │ └──-2,192 B (-0.02%) ++ objects > │ │ ├──────-3,488 B (-0.03%) -- class(XPC_WN_NoMods_NoCall_Proto_JSClass) > │ │ │ ├──-2,176 B (-0.02%) ++ shapes > │ │ │ └──-1,312 B (-0.01%) ++ objects > │ │ ├──────-2,600 B (-0.02%) -- class(Date) > │ │ │ ├──-1,864 B (-0.02%) ++ shapes > │ │ │ └────-736 B (-0.01%) ++ objects > │ │ ├──────-2,456 B (-0.02%) -- class(ctypes) > │ │ │ ├──-1,896 B (-0.02%) ++ shapes > │ │ │ └────-560 B (-0.00%) ++ objects > │ │ ├──────-2,392 B (-0.02%) -- class(nsJSCID) > │ │ │ ├──-2,336 B (-0.02%) ── objects/gc-heap > │ │ │ └─────-56 B (-0.00%) ++ shapes/gc-heap > │ │ ├──────-2,088 B (-0.02%) -- class(String) > │ │ │ ├──-1,544 B (-0.01%) ++ shapes > │ │ │ └────-544 B (-0.00%) ++ objects > │ │ ├──────-1,960 B (-0.02%) -- class(Math) > │ │ │ ├──-1,432 B (-0.01%) ++ shapes > │ │ │ └────-528 B (-0.00%) ++ objects > │ │ ├──────-1,656 B (-0.01%) -- class(DOMExceptionPrototype) > │ │ │ ├──-1,384 B (-0.01%) ++ shapes > │ │ │ └────-272 B (-0.00%) ++ objects > │ │ ├──────-1,648 B (-0.01%) -- class(Error) > │ │ │ ├──-1,056 B (-0.01%) ++ shapes > │ │ │ └────-592 B (-0.01%) ++ objects > │ │ ├──────-1,496 B (-0.01%) -- class(Map) > │ │ │ ├────-896 B (-0.01%) ++ objects > │ │ │ └────-600 B (-0.01%) ++ shapes > │ │ ├──────-1,448 B (-0.01%) -- class(XMLHttpRequestPrototype) > │ │ │ ├──-1,304 B (-0.01%) ++ shapes > │ │ │ └────-144 B (-0.00%) ++ objects > │ │ ├──────-1,296 B (-0.01%) -- class(EventPrototype) > │ │ │ ├──-1,152 B (-0.01%) ++ shapes > │ │ │ └────-144 B (-0.00%) ++ objects > │ │ ├──────-1,064 B (-0.01%) -- class(JSXrayHolder) > │ │ │ ├──-1,008 B (-0.01%) ── objects/gc-heap > │ │ │ └─────-56 B (-0.00%) ++ shapes/gc-heap > │ │ ├──────-1,056 B (-0.01%) -- class(Set) > │ │ │ ├────-544 B (-0.00%) ++ objects > │ │ │ └────-512 B (-0.00%) ++ shapes > │ │ ├────────-872 B (-0.01%) -- class(IDBObjectStorePrototype) > │ │ │ ├──-728 B (-0.01%) ++ shapes > │ │ │ └──-144 B (-0.00%) ++ objects > │ │ ├────────-864 B (-0.01%) -- class(DataViewPrototype) > │ │ │ ├──-560 B (-0.00%) ++ shapes/gc-heap > │ │ │ └──-304 B (-0.00%) ++ objects > │ │ ├────────-816 B (-0.01%) -- class(SavedFrame) > │ │ │ ├──-464 B (-0.00%) ++ objects > │ │ │ └──-352 B (-0.00%) ++ shapes/gc-heap > │ │ ├────────-720 B (-0.01%) -- class(IDBDatabasePrototype) > │ │ │ ├──-640 B (-0.01%) ++ shapes > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-712 B (-0.01%) -- class(IDBIndexPrototype) > │ │ │ ├──-632 B (-0.01%) ++ shapes > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-576 B (-0.01%) -- class(WeakMap) > │ │ │ ├──-320 B (-0.00%) ++ objects > │ │ │ └──-256 B (-0.00%) ++ shapes/gc-heap > │ │ ├────────-568 B (-0.00%) -- class(URLPrototype) > │ │ │ ├──-488 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-560 B (-0.00%) -- class(???) > │ │ │ ├──-480 B (-0.00%) ++ shapes > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-512 B (-0.00%) -- class(ExceptionPrototype) > │ │ │ ├──-432 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-496 B (-0.00%) -- class(XPC_WN_ModsAllowed_NoCall_Proto_JSClass) > │ │ │ ├──-304 B (-0.00%) ++ shapes > │ │ │ └──-192 B (-0.00%) ++ objects > │ │ ├────────-464 B (-0.00%) -- class(IDBTransactionPrototype) > │ │ │ ├──-384 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-440 B (-0.00%) -- class(nsXPCComponents_Utils) > │ │ │ ├──-344 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-96 B (-0.00%) ++ objects > │ │ ├────────-416 B (-0.00%) -- class(IDBRequestPrototype) > │ │ │ ├──-336 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-384 B (-0.00%) -- class(IDBCursorPrototype) > │ │ │ ├──-304 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-368 B (-0.00%) -- class(IDBMutableFilePrototype) > │ │ │ ├──-288 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-368 B (-0.00%) -- class(Iterator) > │ │ │ ├──-224 B (-0.00%) ++ shapes > │ │ │ └──-144 B (-0.00%) ++ objects > │ │ ├────────-352 B (-0.00%) -- class(MessageEventPrototype) > │ │ │ ├──-272 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-344 B (-0.00%) -- class(Number) > │ │ │ ├──-248 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-96 B (-0.00%) ++ objects > │ │ ├────────-320 B (-0.00%) -- class(IDBKeyRangePrototype) > │ │ │ ├──-240 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-312 B (-0.00%) -- class(EventTargetPrototype) > │ │ │ ├──-232 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-312 B (-0.00%) -- class(IDBFactoryPrototype) > │ │ │ ├──-232 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-312 B (-0.00%) -- class(nsXPCConstructor) > │ │ │ ├──-160 B (-0.00%) ── objects/gc-heap > │ │ │ └──-152 B (-0.00%) ++ shapes/gc-heap > │ │ ├────────-304 B (-0.00%) -- class(WorkerPrototype) > │ │ │ ├──-224 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-296 B (-0.00%) -- class(Library) > │ │ │ ├──-192 B (-0.00%) ++ objects > │ │ │ └──-104 B (-0.00%) ++ shapes/gc-heap > │ │ ├────────-296 B (-0.00%) -- class(XMLHttpRequestEventTargetPrototype) > │ │ │ ├──-280 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-16 B (-0.00%) ── objects/gc-heap > │ │ ├────────-288 B (-0.00%) -- class(FilePrototype) > │ │ │ ├──-208 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-280 B (-0.00%) -- class(BlobPrototype) > │ │ │ ├──-200 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-280 B (-0.00%) -- class(CDataFinalizer) > │ │ │ ├──-200 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-280 B (-0.00%) -- class(ChromeMessageSender) > │ │ │ ├──-224 B (-0.00%) ── objects/gc-heap > │ │ │ └───-56 B (-0.00%) ++ shapes/gc-heap > │ │ ├────────-280 B (-0.00%) -- class(TextDecoderPrototype) > │ │ │ ├──-200 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-256 B (-0.00%) -- class(IDBOpenDBRequestPrototype) > │ │ │ ├──-176 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-248 B (-0.00%) -- class(Boolean) > │ │ │ ├──-152 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-96 B (-0.00%) ++ objects > │ │ ├────────-248 B (-0.00%) -- class(IDBDatabase) > │ │ │ ├──-192 B (-0.00%) ── objects/gc-heap > │ │ │ └───-56 B (-0.00%) ++ shapes/gc-heap > │ │ ├────────-248 B (-0.00%) -- class(MozWakeLockPrototype) > │ │ │ ├──-168 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-248 B (-0.00%) -- class(RegExpStatics) > │ │ │ ├──-192 B (-0.00%) ++ objects > │ │ │ └───-56 B (-0.00%) ++ shapes/gc-heap > │ │ ├────────-248 B (-0.00%) -- class(Set Iterator) > │ │ │ ├──-136 B (-0.00%) ++ shapes/gc-heap > │ │ │ └──-112 B (-0.00%) ++ objects > │ │ ├────────-240 B (-0.00%) -- class(Int64) > │ │ │ ├──-160 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-240 B (-0.00%) -- class(PromisePrototype) > │ │ │ ├──-160 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-240 B (-0.00%) -- class(UInt64) > │ │ │ ├──-160 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-224 B (-0.00%) -- class(IDBCursorWithValuePrototype) > │ │ │ ├──-144 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-224 B (-0.00%) -- class(IDBVersionChangeEventPrototype) > │ │ │ ├──-144 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-216 B (-0.00%) -- class(Array Iterator) > │ │ │ ├──-112 B (-0.00%) ++ objects > │ │ │ └──-104 B (-0.00%) ++ shapes/gc-heap > │ │ ├────────-216 B (-0.00%) -- class(ArrayBufferPrototype) > │ │ │ ├──-136 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-216 B (-0.00%) -- class(IDBOpenDBRequest) > │ │ │ ├──-160 B (-0.00%) ── objects/gc-heap > │ │ │ └───-56 B (-0.00%) ++ shapes/gc-heap > │ │ ├────────-216 B (-0.00%) -- class(nsXPCComponents_Results) > │ │ │ ├──-120 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-96 B (-0.00%) ++ objects > │ │ ├────────-208 B (-0.00%) -- class(JSON) > │ │ │ ├──-128 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-184 B (-0.00%) -- class(String Iterator) > │ │ │ ├──-104 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-184 B (-0.00%) -- class(Uint8ArrayPrototype) > │ │ │ ├──-104 B (-0.00%) ++ shapes/gc-heap > │ │ │ └───-80 B (-0.00%) ++ objects > │ │ ├────────-160 B (-0.00%) -- class(ChromeWorkerPrototype) > │ │ │ ├───-80 B (-0.00%) ++ objects > │ │ │ └───-80 B (-0.00%) ++ shapes/gc-heap > │ │ ├────────-152 B (-0.00%) -- class(CABI) > │ │ │ ├───-96 B (-0.00%) ── objects/gc-heap > │ │ │ └───-56 B (-0.00%) ++ shapes/gc-heap > │ │ ├────────-120 B (-0.00%) -- class(ChromeMessageBroadcaster) > │ │ │ ├───-64 B (-0.00%) ── objects/gc-heap > │ │ │ └───-56 B (-0.00%) ++ shapes/gc-heap > │ │ ├─────────-88 B (-0.00%) -- class(ForOfPIC) > │ │ │ ├──-56 B (-0.00%) ++ shapes/gc-heap > │ │ │ └──-32 B (-0.00%) ── objects/gc-heap > │ │ ├─────────-88 B (-0.00%) -- class(IDBFactory) > │ │ │ ├──-56 B (-0.00%) ++ shapes/gc-heap > │ │ │ └──-32 B (-0.00%) ── objects/gc-heap > │ │ ├─────────-88 B (-0.00%) -- class(Promise) > │ │ │ ├──-56 B (-0.00%) ++ shapes/gc-heap > │ │ │ └──-32 B (-0.00%) ── objects/gc-heap > │ │ ├─────────-88 B (-0.00%) -- class(TextDecoder) > │ │ │ ├──-56 B (-0.00%) ++ shapes/gc-heap > │ │ │ └──-32 B (-0.00%) ── objects/gc-heap > │ │ ├─────────-88 B (-0.00%) -- class(Worker) > │ │ │ ├──-56 B (-0.00%) ++ shapes/gc-heap > │ │ │ └──-32 B (-0.00%) ── objects/gc-heap > │ │ ├─────────-88 B (-0.00%) -- class(nsXPCComponents) > │ │ │ ├──-56 B (-0.00%) ++ shapes/gc-heap > │ │ │ └──-32 B (-0.00%) ── objects/gc-heap > │ │ ├─────────-88 B (-0.00%) -- class(nsXPCComponents_Constructor) > │ │ │ ├──-56 B (-0.00%) ++ shapes/gc-heap > │ │ │ └──-32 B (-0.00%) ── objects/gc-heap > │ │ └─────────-72 B (-0.00%) -- class(StopIteration) > │ │ ├──-56 B (-0.00%) ++ shapes/gc-heap > │ │ └──-16 B (-0.00%) ── objects/gc-heap > │ ├────-958,280 B (-8.35%) -- scripts > │ │ ├──-774,432 B (-6.75%) ── gc-heap [-] > │ │ └──-183,848 B (-1.60%) ── malloc-heap/data > │ ├────-180,040 B (-1.57%) -- type-inference > │ │ ├───-96,480 B (-0.84%) ── type-scripts [-] > │ │ ├───-49,168 B (-0.43%) ── allocation-site-tables [-] > │ │ ├───-33,352 B (-0.29%) ── object-type-tables [-] > │ │ └────-1,040 B (-0.01%) ── array-type-tables [-] > │ ├─────-82,432 B (-0.72%) ── compartment-tables [-] > │ ├─────-65,536 B (-0.57%) ── cross-compartment-wrapper-table [-] > │ ├──────-3,072 B (-0.03%) -- baseline > │ │ ├──-2,048 B (-0.02%) ── fallback-stubs [-] > │ │ └──-1,024 B (-0.01%) ── data [-] > │ ├──────-1,028 B (-0.01%) ── inner-views [-] > │ ├────────-488 B (-0.00%) ── regexp-compartment [-] > │ └────────-432 B (-0.00%) ── compartment-object [-] Lots of Object, Function, Call, and Array objects, which aren't surprising. The high number of FakeBackstagePass objects is interesting. Here is the biggest of the de-merged compartments: > ├────594,544 B (05.18%) -- compartment([System Principal], resource://gre/modules/AppsServiceChild.jsm) > │ ├──527,000 B (04.59%) -- classes > │ │ ├──428,736 B (03.73%) -- class(Object) > │ │ │ ├──336,160 B (02.93%) ++ objects > │ │ │ └───92,576 B (00.81%) ++ shapes > │ │ ├───47,680 B (00.42%) -- class(Function) > │ │ │ ├──31,360 B (00.27%) ++ objects > │ │ │ └──16,320 B (00.14%) ++ shapes > │ │ ├───23,584 B (00.21%) -- class(Array) > │ │ │ ├──22,192 B (00.19%) ++ objects > │ │ │ └───1,392 B (00.01%) ++ shapes > │ │ ├───10,728 B (00.09%) -- class(XPCWrappedNative_NoHelper) > │ │ │ ├──10,464 B (00.09%) ++ objects > │ │ │ └─────264 B (00.00%) ++ shapes > │ │ ├────9,080 B (00.08%) -- class(Call) > │ │ │ ├──8,736 B (00.08%) ── objects/gc-heap > │ │ │ └────344 B (00.00%) ++ shapes > │ │ ├────3,288 B (00.03%) -- class(BackstagePass) > │ │ │ ├──2,192 B (00.02%) ++ objects > │ │ │ └──1,096 B (00.01%) ++ shapes > │ │ ├────1,304 B (00.01%) -- class(Proxy) > │ │ │ ├──1,248 B (00.01%) ── objects/gc-heap > │ │ │ └─────56 B (00.00%) ++ shapes/gc-heap > │ │ ├────1,184 B (00.01%) -- class(Block) > │ │ │ ├────640 B (00.01%) ++ objects > │ │ │ └────544 B (00.00%) ++ shapes > │ │ ├──────512 B (00.00%) -- class(XPC_WN_NoMods_NoCall_Proto_JSClass) > │ │ │ ├──320 B (00.00%) ++ shapes > │ │ │ └──192 B (00.00%) ── objects/gc-heap > │ │ ├──────248 B (00.00%) -- class(nsXPCComponents_Utils) > │ │ │ ├──152 B (00.00%) ++ shapes/gc-heap > │ │ │ └───96 B (00.00%) ++ objects > │ │ ├──────152 B (00.00%) -- class(ScriptSource) > │ │ │ ├───96 B (00.00%) ── objects/gc-heap > │ │ │ └───56 B (00.00%) ++ shapes/gc-heap > │ │ ├──────120 B (00.00%) -- class(nsXPCComponents_Classes) > │ │ │ ├───88 B (00.00%) ++ shapes/gc-heap > │ │ │ └───32 B (00.00%) ── objects/gc-heap > │ │ ├──────120 B (00.00%) -- class(nsXPCComponents_Interfaces) > │ │ │ ├───88 B (00.00%) ++ shapes/gc-heap > │ │ │ └───32 B (00.00%) ── objects/gc-heap > │ │ ├───────88 B (00.00%) -- class(nsJSCID) > │ │ │ ├──56 B (00.00%) ++ shapes/gc-heap > │ │ │ └──32 B (00.00%) ── objects/gc-heap > │ │ ├───────88 B (00.00%) -- class(nsJSIID) > │ │ │ ├──56 B (00.00%) ++ shapes/gc-heap > │ │ │ └──32 B (00.00%) ── objects/gc-heap > │ │ └───────88 B (00.00%) -- class(nsXPCComponents) > │ │ ├──56 B (00.00%) ++ shapes/gc-heap > │ │ └──32 B (00.00%) ── objects/gc-heap > │ ├───35,912 B (00.31%) -- type-inference > │ │ ├──33,352 B (00.29%) ── object-type-tables [+] > │ │ ├───1,120 B (00.01%) ── type-scripts [+] > │ │ ├───1,040 B (00.01%) ── array-type-tables [+] > │ │ └─────400 B (00.00%) ── allocation-site-tables [+] > │ ├───16,960 B (00.15%) ── compartment-tables [+] > │ ├────8,192 B (00.07%) ── cross-compartment-wrapper-table [+] > │ ├────5,984 B (00.05%) -- scripts > │ │ ├──4,896 B (00.04%) ── gc-heap [+] > │ │ └──1,088 B (00.01%) ── malloc-heap/data > │ ├──────432 B (00.00%) ── compartment-object [+] > │ └───────64 B (00.00%) ── regexp-compartment [+] Here's one from the middle of the de-merged pack: > ├─────56,544 B (00.49%) -- compartment([System Principal], resource://gre/modules/DownloadIntegration.jsm) > │ ├──37,808 B (00.33%) -- classes > │ │ ├──16,456 B (00.14%) -- class(Function) > │ │ │ ├──12,576 B (00.11%) ++ objects > │ │ │ └───3,880 B (00.03%) ++ shapes > │ │ ├───6,504 B (00.06%) -- class(Object) > │ │ │ ├──4,680 B (00.04%) ++ shapes > │ │ │ └──1,824 B (00.02%) ++ objects > │ │ ├───4,288 B (00.04%) -- class(BackstagePass) > │ │ │ ├──2,192 B (00.02%) ++ objects > │ │ │ └──2,096 B (00.02%) ++ shapes > │ │ ├───1,856 B (00.02%) -- class(Array) > │ │ │ ├──1,072 B (00.01%) ++ shapes/gc-heap > │ │ │ └────784 B (00.01%) ++ objects > │ │ ├───1,816 B (00.02%) -- class(Block) > │ │ │ ├──1,152 B (00.01%) ── objects/gc-heap > │ │ │ └────664 B (00.01%) ++ shapes > │ │ ├───1,112 B (00.01%) -- class(Call) > │ │ │ ├──1,016 B (00.01%) ++ shapes > │ │ │ └─────96 B (00.00%) ── objects/gc-heap > │ │ ├─────800 B (00.01%) -- class(RegExp) > │ │ │ ├──576 B (00.01%) ++ shapes/gc-heap > │ │ │ └──224 B (00.00%) ++ objects > │ │ ├─────640 B (00.01%) -- class(Set) > │ │ │ ├──384 B (00.00%) ++ shapes/gc-heap > │ │ │ └──256 B (00.00%) ++ objects > │ │ ├─────600 B (00.01%) -- class(Map) > │ │ │ ├──408 B (00.00%) ++ shapes/gc-heap > │ │ │ └──192 B (00.00%) ++ objects > │ │ ├─────528 B (00.00%) -- class(XPC_WN_NoMods_NoCall_Proto_JSClass) > │ │ │ ├──272 B (00.00%) ++ shapes/gc-heap > │ │ │ └──256 B (00.00%) ── objects/gc-heap > │ │ ├─────424 B (00.00%) -- class(Proxy) > │ │ │ ├──368 B (00.00%) ── objects/gc-heap > │ │ │ └───56 B (00.00%) ++ shapes/gc-heap > │ │ ├─────368 B (00.00%) -- class(Iterator) > │ │ │ ├──224 B (00.00%) ++ shapes > │ │ │ └──144 B (00.00%) ++ objects > │ │ ├─────248 B (00.00%) -- class(RegExpStatics) > │ │ │ ├──192 B (00.00%) ++ objects > │ │ │ └───56 B (00.00%) ++ shapes/gc-heap > │ │ ├─────248 B (00.00%) -- class(Set Iterator) > │ │ │ ├──136 B (00.00%) ++ shapes/gc-heap > │ │ │ └──112 B (00.00%) ++ objects > │ │ ├─────248 B (00.00%) -- class(nsXPCComponents_Interfaces) > │ │ │ ├──152 B (00.00%) ++ shapes/gc-heap > │ │ │ └───96 B (00.00%) ++ objects > │ │ ├─────216 B (00.00%) -- class(Array Iterator) > │ │ │ ├──112 B (00.00%) ++ objects > │ │ │ └──104 B (00.00%) ++ shapes/gc-heap > │ │ ├─────216 B (00.00%) -- class(nsXPCComponents_Utils) > │ │ │ ├──120 B (00.00%) ++ shapes/gc-heap > │ │ │ └───96 B (00.00%) ++ objects > │ │ ├─────208 B (00.00%) -- class(PromisePrototype) > │ │ │ ├──128 B (00.00%) ++ shapes/gc-heap > │ │ │ └───80 B (00.00%) ++ objects > │ │ ├─────184 B (00.00%) -- class(String Iterator) > │ │ │ ├──104 B (00.00%) ++ shapes/gc-heap > │ │ │ └───80 B (00.00%) ++ objects > │ │ ├─────152 B (00.00%) -- class(ScriptSource) > │ │ │ ├───96 B (00.00%) ── objects/gc-heap > │ │ │ └───56 B (00.00%) ++ shapes/gc-heap > │ │ ├─────152 B (00.00%) -- class(nsJSIID) > │ │ │ ├───96 B (00.00%) ── objects/gc-heap > │ │ │ └───56 B (00.00%) ++ shapes/gc-heap > │ │ ├─────120 B (00.00%) -- class(nsXPCComponents_Classes) > │ │ │ ├───88 B (00.00%) ++ shapes/gc-heap > │ │ │ └───32 B (00.00%) ── objects/gc-heap > │ │ ├──────88 B (00.00%) -- class(nsJSCID) > │ │ │ ├──56 B (00.00%) ++ shapes/gc-heap > │ │ │ └──32 B (00.00%) ── objects/gc-heap > │ │ ├──────88 B (00.00%) -- class(nsXPCComponents) > │ │ │ ├──56 B (00.00%) ++ shapes/gc-heap > │ │ │ └──32 B (00.00%) ── objects/gc-heap > │ │ ├──────88 B (00.00%) -- class(nsXPCComponents_Results) > │ │ │ ├──56 B (00.00%) ++ shapes/gc-heap > │ │ │ └──32 B (00.00%) ── objects/gc-heap > │ │ ├──────88 B (00.00%) -- class(nsXPCConstructor) > │ │ │ ├──56 B (00.00%) ++ shapes/gc-heap > │ │ │ └──32 B (00.00%) ── objects/gc-heap > │ │ └──────72 B (00.00%) -- class(StopIteration) > │ │ ├──56 B (00.00%) ++ shapes/gc-heap > │ │ └──16 B (00.00%) ── objects/gc-heap > │ ├───9,904 B (00.09%) -- scripts > │ │ ├──7,920 B (00.07%) ── gc-heap [+] > │ │ └──1,984 B (00.02%) ── malloc-heap/data > │ ├───5,632 B (00.05%) ── compartment-tables [+] > │ ├───2,048 B (00.02%) ── cross-compartment-wrapper-table [+] > │ ├─────656 B (00.01%) -- type-inference > │ │ ├──336 B (00.00%) ── type-scripts [+] > │ │ ├──208 B (00.00%) ── allocation-site-tables [+] > │ │ └──112 B (00.00%) ── array-type-tables [+] > │ ├─────432 B (00.00%) ── compartment-object [+] > │ └──────64 B (00.00%) ── regexp-compartment [+] Here's one of the smallest de-merged compartments: > ├─────19,504 B (00.17%) -- compartment([System Principal], resource://gre/modules/reflect.jsm) > │ ├──15,120 B (00.13%) -- classes > │ │ ├───7,544 B (00.07%) -- class(Function) > │ │ │ ├──5,392 B (00.05%) ++ objects > │ │ │ └──2,152 B (00.02%) ++ shapes > │ │ ├───2,944 B (00.03%) -- class(BackstagePass) > │ │ │ ├──2,192 B (00.02%) ++ objects > │ │ │ └────752 B (00.01%) ++ shapes > │ │ ├───2,344 B (00.02%) -- class(Object) > │ │ │ ├──1,592 B (00.01%) ++ shapes > │ │ │ └────752 B (00.01%) ++ objects > │ │ ├───1,696 B (00.01%) -- class(Array) > │ │ │ ├──1,072 B (00.01%) ++ shapes/gc-heap > │ │ │ └────624 B (00.01%) ++ objects > │ │ ├─────208 B (00.00%) -- class(XPC_WN_NoMods_NoCall_Proto_JSClass) > │ │ │ ├──144 B (00.00%) ++ shapes/gc-heap > │ │ │ └───64 B (00.00%) ── objects/gc-heap > │ │ ├─────152 B (00.00%) -- class(ScriptSource) > │ │ │ ├───96 B (00.00%) ── objects/gc-heap > │ │ │ └───56 B (00.00%) ++ shapes/gc-heap > │ │ ├──────88 B (00.00%) -- class(Module) > │ │ │ ├──56 B (00.00%) ++ shapes/gc-heap > │ │ │ └──32 B (00.00%) ── objects/gc-heap > │ │ ├──────88 B (00.00%) -- class(nsXPCComponents) > │ │ │ ├──56 B (00.00%) ++ shapes/gc-heap > │ │ │ └──32 B (00.00%) ── objects/gc-heap > │ │ └──────56 B (00.00%) ++ class(Call)/shapes/gc-heap > │ ├───2,304 B (00.02%) ── compartment-tables [+] > │ ├───1,152 B (00.01%) -- type-inference > │ │ ├──1,040 B (00.01%) ── allocation-site-tables [+] > │ │ └────112 B (00.00%) ── array-type-tables [+] > │ ├─────432 B (00.00%) ── compartment-object [+] > │ ├─────304 B (00.00%) -- scripts > │ │ ├──288 B (00.00%) ── gc-heap [+] > │ │ └───16 B (00.00%) ── malloc-heap/data > │ ├─────128 B (00.00%) ── cross-compartment-wrapper-table [+] > │ └──────64 B (00.00%) ── regexp-compartment [+] The smaller the compartment, the more that Function objects dominate. And BackstagePass objects take up quite a bit of space too.
> (BTW, the startup cache was disabled in bug 988880, and then bug 999631 fiddled > with the disabling... it must have broken the disabling somehow.) It did break it. I've filed bug 1111948 and will shortly upload a fix for it. With that patch applied, the startup-cache isn't present and the extra memory use caused by de-merging compartments is down to ~7 MiB for the b2g process.
(In reply to Nicholas Nethercote [:njn] from comment #21) > I redid the measurements because we now have per-class reporting in > about:memory. I'll just discuss the b2g process, since that's the most > important one. This is great analysis. Thank you! > The high number of FakeBackstagePass objects is interesting. How many of these are there? There should be exactly as many FakeBackstagePasses as there are de-merged compartments (since that's our stand-in object for the global). They're just empty objects at the beginning, so their size is presumably the result of all of the properties defined on them. > The smaller the compartment, the more that Function objects dominate. Do we know what Function objects they are? Are these just standard constructors and stuff? If so, I wonder if we could do stuff to share them across compartments. > And > BackstagePass objects take up quite a bit of space too. Those are the globals. Are the sizes reasonable for a global? In theory, we should have equivalent overhead of defined properties in either the FakeBackstagePass or the BackstagePass case. So if F is the size of a given FakeBackstagePass and B if the size of its corresponding demerged BackstagePass global, then sizeof(B) - sizeof(F) should equal the overhead of all of the global slots. Does that add up? Stepping back, we have some amount of unavoidable per-global overhead: * The slots on the global * The size of the standard constructors and prototypes themselves that we need to set up How do the nominal values there compare to what we're seeing? Is there fat we can cut somewhere? There's also the issue of the shapes. Shapes for standard objects seem ripe for sharing across compartments, except for the fact that we use the shape to determine the compartment of an object. Any clever ideas?
> Do we know what Function objects they are? Are these just standard constructors and stuff? I don't know. I'm definitely open to the idea of providing more granularity for Function objects in the memory reporters, if somebody can suggest a good way to do so. (Likewise with Object and Array objects, which tend to be very common.)
(In reply to Nicholas Nethercote [:njn] from comment #24) > > Do we know what Function objects they are? Are these just standard constructors and stuff? > > I don't know. I'm definitely open to the idea of providing more granularity > for Function objects in the memory reporters, if somebody can suggest a good > way to do so. With functions, I think it would be super useful to know if they're scripted or JSNative-backed, and if JSNative-backed, which JSNatives. In particular, it would be good to know if there are any duplicated JSNatives in a given compartment, or whether it's really just the sum of all the standard objects.
Blocks: nukeb2g
I'm looking at bug 1186409 which sort of reuses some of this code. I'll try to work out whether it makes sense to remove it first, or at the same time.
Assignee: nobody → continuation
Depends on: 1357828
No longer depends on: 997906
Depends on: 1363544
Blocks: 1186409
Blocks: 1176342
Depends on: 1365417
Attachment #8399221 - Attachment is obsolete: true
Attachment #8399222 - Attachment is obsolete: true
Attachment #8401077 - Attachment is obsolete: true
Comment on attachment 8869182 [details] Bug 989373, part 2 - Remove unused JS API methods related to global sharing while compiling to functions. https://reviewboard.mozilla.org/r/140790/#review144360 yay deleting code
Attachment #8869182 - Flags: review?(shu) → review+
Comment on attachment 8869181 [details] Bug 989373, part 1 - Remove pref for reusing globals with JSMs. https://reviewboard.mozilla.org/r/140788/#review144734 ::: js/xpconnect/loader/mozJSComponentLoader.cpp:655 (Diff revision 1) > - // can't do lazy source because we compile things as functions > - // (rather than script), and lazy source isn't supported in that > + // fast. Content processes don't use the startup cache, so we want them > + // to use non-lazy source code to enable lazy parsing. I'd also remove the bit about content processes, since that's only sort of true now. Maybe something like "When we're not using the startup cache, we want to use non-lazy source code so that we can use lazy parsing." ::: js/xpconnect/loader/mozJSComponentLoader.cpp (Diff revision 1) > - // Note: exceptions will get handled further down; > - // don't early return for them here. I think this comment is actually relevant to the Compile() calls too, so maybe move it above that line rather than removing it?
Attachment #8869181 - Flags: review?(kmaglione+bmo) → review+
Comment on attachment 8869183 [details] Bug 989373, part 3 - |function| is always null in ObjectForLocation. https://reviewboard.mozilla.org/r/140792/#review144742 ::: js/xpconnect/loader/mozJSComponentLoader.cpp:745 (Diff revision 1) > Compile(cx, options, buf.get(), bytesRead, &script); > } > // Propagate the exception, if one exists. Also, don't leave the stale > // exception on this context. > - if (!script && !function && aPropagateExceptions && > + if (!script && aPropagateExceptions && > jsapi.HasException()) { Nit: Should fit on the previous line now. ::: js/xpconnect/loader/mozJSComponentLoader.cpp:755 (Diff revision 1) > > - // We must have a script or a function (but not both!) here. We have a > - // script when we're not reusing the loader global, and a function > - // otherwise. > - MOZ_ASSERT(!!script != !!function); > MOZ_ASSERT(!!script == JS_IsGlobalObject(obj)); `!!script` is always true here, so please remove.
Attachment #8869183 - Flags: review?(kmaglione+bmo) → review+
Comment on attachment 8869184 [details] Bug 989373, part 4 - Remove reuse global flag from subscript loader. https://reviewboard.mozilla.org/r/140794/#review144746 r=me with nits addressed. I'm very happy to see this code go away :) ::: commit-message-778d5:3 (Diff revision 1) > +|targetObject| in DoLoadSubScriptWithOptions will always be a global > +object, so the boolean values we pass around to determine if a global This isn't quite true. We can (and do) still pass non-global target objects, and allow compiling for those scopes. The only difference now is that we no longer special case the pseudo-globals generated by the b2g module loader when they're used as targets. ::: js/xpconnect/loader/mozJSSubScriptLoader.cpp:583 (Diff revision 1) > mozJSComponentLoader* loader = mozJSComponentLoader::Get(); > loader->FindTargetObject(cx, &targetObj); > > - // We base reusingGlobal off of what the loader told us, but we may not > + MOZ_ASSERT(JS_IsGlobalObject(targetObj)); We should only need to do this if options.target is not defined, now.
Attachment #8869184 - Flags: review?(kmaglione+bmo) → review+
Comment on attachment 8869185 [details] Bug 989373, part 5 - Eliminate |function| from subscript loader. https://reviewboard.mozilla.org/r/140796/#review144752 ::: js/xpconnect/loader/mozJSSubScriptLoader.cpp:681 (Diff revision 1) > - &function)) > { > return NS_OK; > } > } else { > cache = nullptr; Not really related to this change, but can you reverse the order of these branches (`if (script) { cache = nullptr; } ...`) and add a comment that we're nulling the cache so we don't bother writing the script back to the cache if that's where we got it from? This confuses me every time I see it, and it took me a while to decipher it again to figure out if it should be affected by the removal of function compilation.
Attachment #8869185 - Flags: review?(kmaglione+bmo) → review+
Comment on attachment 8869186 [details] Bug 989373, part 6 - Rename |obj| to |thisObj| in PrepareObjectForLocation. https://reviewboard.mozilla.org/r/140798/#review144754 ::: commit-message-25ae8:6 (Diff revision 1) > +Bug 989373, part 6 - Rename |obj| to |thisObj| in PrepareObjectForLocation. r=kmag > + > +The name obj is not very descriptive, and a later patch will add > +another object to this method, so rename it to thisObj. thisObj is the > +object we set properties on for a particular .jsm. With global > +sharing, it will be different than the global. Can you also add a comment about this where `thisObj` is defined?
Attachment #8869186 - Flags: review?(kmaglione+bmo) → review+
Comment on attachment 8869187 [details] Bug 989373, part 7 - Add new method to create a loader global. https://reviewboard.mozilla.org/r/140800/#review144756 ::: js/xpconnect/loader/mozJSComponentLoader.cpp:539 (Diff revision 1) > + bool createdNewGlobal = false; > + RootedObject globalObj(aCx); > + > + if (!mLoaderGlobal) { > + CreateLoaderGlobal(aCx, MapURIToAddonID(aURI), &globalObj); > + createdNewGlobal = true; Can we check that the global got created successfully before we set this? ::: js/xpconnect/loader/mozJSComponentLoader.cpp:548 (Diff revision 1) > + // sharing globals between jsms, they won't be the same. > + // See bug 1186409. > + RootedObject thisObj(aCx, globalObj); > NS_ENSURE_TRUE(thisObj, nullptr); > > - JSAutoCompartment ac(aCx, thisObj); > + JSAutoCompartment ac(aCx, globalObj); Is there any reason we shouldn't still use `thisObj` here? We should wind up in the same compartment either way, and `thisObj` is probably what we care most about at this point.
Attachment #8869187 - Flags: review?(kmaglione+bmo) → review+
(In reply to Kris Maglione [:kmag] (busy; behind on reviews) from comment #42) > Can we check that the global got created successfully before we set this? We don't actually check createdNewGlobal until after we're already bailed out if globalObj wasn't set. So it doesn't matter. But I agree it is confusing in practice. I had the same reaction. I guess I should add that check. > Is there any reason we shouldn't still use `thisObj` here? We should wind up > in the same compartment either way, and `thisObj` is probably what we care > most about at this point. Sure, I could do that.
Attachment #8869188 - Flags: review?(kmaglione+bmo) → review+
Pushed by amccreight@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/b2b8fadcfa75 part 1 - Remove pref for reusing globals with JSMs. r=kmag https://hg.mozilla.org/integration/autoland/rev/36bb469c723c part 2 - Remove unused JS API methods related to global sharing while compiling to functions. r=shu https://hg.mozilla.org/integration/autoland/rev/d9f3972b7d97 part 3 - |function| is always null in ObjectForLocation. r=kmag https://hg.mozilla.org/integration/autoland/rev/d76a99d0f147 part 4 - Remove reuse global flag from subscript loader. r=kmag https://hg.mozilla.org/integration/autoland/rev/60a6e210bb3b part 5 - Eliminate |function| from subscript loader. r=kmag https://hg.mozilla.org/integration/autoland/rev/67231a14bdc9 part 6 - Rename |obj| to |thisObj| in PrepareObjectForLocation. r=kmag https://hg.mozilla.org/integration/autoland/rev/249446e1ed68 part 7 - Add new method to create a loader global. r=kmag https://hg.mozilla.org/integration/autoland/rev/da7db7d677e7 part 8 - mLoaderGlobal is always null. r=kmag
No longer blocks: 1369194
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: