We've had bug 764220 open on the CPG memory regression for six months now. Although it's a MemShrink:P1, it hasn't gotten the attention it deserves.
FWIW, I think part of this stems from the fact that the MemShrink team is often ineffective at getting others to fix bugs that we think are a priority, perhaps because we don't have an Important Person prodding other managers to worry about our bugs. So when we can't fix a bug ourselves, it often languishes. (Not to dismiss the heroic efforts of many people outside the core MemShrink group who have fixed memory bugs!) The CPG memory regression and bug 689623 are good examples of this. There are a lot of different approaches we could take to reducing the overhead from CPG. I'd think that a first step would be trying to apply bug 798491 (the B2G patch to load most chrome code into one compartment) to desktop Firefox, but I don't fully understand the trade-offs here. CPG resulted in a memory regression for both content and chrome JS, and we may need different techniques to address them. But ultimately, I think this is an eminently solvable problem; we just need to convince someone to look at it. And as engineers, the main way we have to effect that is to bring it up, like you did. So thanks. :) -Justin On Sun, Jan 20, 2013 at 2:37 PM, Gregory Szorc <[email protected]> wrote: > I'm writing to the Platform list as a developer that maintains a significant > amount of JavaScript for Firefox. Much of the JavaScript I maintain is for > large backend features, such as Sync and Firefox Health Report. These > features are thousands of lines of code (mostly JavaScript) and interact > with many systems in Firefox. These backend systems tend to perform many of > the same tasks, so there is code shared between them in the form of JSMs. To > reduce redundant code (therefore bugs) and development costs, there is > obviously the incentive to share as much code as possible. > > I'd like to start a discussion about an issue that has been troubling me for > a while: the performance overhead of separate compartments per JSM. I've > previously brought this up in bugs and with a few individuals. I wanted to > raise awareness by posting here. I apologize in advance if I make a few > semantic mistakes on things like "globals" and "compartments" and the > overhead of cross-compartment operations: I'm not a core platform hacker! > > Ever since Compartment per Global (CPG) landed, JS modules imported with > Cu.import now get their own compartment (at least on desktop Firefox - I'm > told they share a compartment on B2G for performance reasons). This is all > nice in theory. You even get a line item in about:memory to see if your > module is doing anything wonky! > > Unfortunately, this change has a few unfortunate side-effects: > > a) Memory overhead for each compartment > b) Perf losses due to crossing compartments > > Assuming the about:memory compartment numbers are correct, each imported JS > module seems to consume at *least* ~55kb (numbers are similar on both OS X > and Windows Nightly builds). > > Furthermore, there appear to be some scenarios where crossing compartments > has a horrible effect on performance. For example, it is my understanding > that crossing compartments can sometimes copy data. I believe this always > holds for strings. See bug 806087 for example. Hundreds of MBs of > "string-chars/huge" are seemingly being copied between JSMs/compartments. > While this specific bug number is resolved, the underlying copying issue > remains AFAIK. > > Sadly, these two issues have a negative influence on how I write JavaScript > code. > > I'm of the camp that tends to write many, small, standalone JSMs rather than > large and monolithic ones. I find the resulting code is easier to comprehend > and test. As an added bonus, anybody can come along later and reuse an > individual module. This includes add-ons. Yay code reuse! The end result is > less overall code being written and debugged and higher test coverage. I > like to think this means the quality of the code base is higher and new > features can be rolled out quicker (due to code reuse). I hold strong > convictions that this code "architecture" is superior. > > With separate compartments per module, I've been put in a tough position. I > have to weigh the code maintainability advantages of multiple modules > against memory usage and performance overhead. If I create dozens of small, > reusable, and specifically-targeted JSMs, I've got the Perf team giving me > the stink eye for increasing memory usage and cross-compartment overhead. If > I write JSMs that are thousands of lines long, I'm creating technical debt > and increasing the barrier to change. > > This is a Kobayashi Maru (no win) scenario. Firefox and other Gecko apps > suffer with both ends of the spectrum. Finding a compromise between the two > extremes is difficult if not impossible in some scenarios. Furthermore, code > is always changing thus the conditions influencing the decision are always > changing. > > That's my problem. And, it's a problem that every large JavaScript feature > faces. And, with groups like Jetpack talking about landing lots of reusable > JSMs in the tree, I think it's a problem that will only get worse over time. > > Now, what can we do about it? > > I'd like to live in a world where you are not significantly penalized for > creating multiple, loosely coupled JSMs. Here are some ideas: > > * Reduce the memory overhead of compartments (I believe this is already > being worked on). > * Have all or most of chrome-privileged JS share the same compartment (like > on B2G). It's my understanding the CPG decision was largely driven by > content/security requirements and chrome just got caught up in it. > * Eliminate excessive copying and other perf issues associated with sending > objects across compartments. > * Allow JSMs to be imported into specific named compartments. > * (Hacky) Build system magic to "concatenate" or merge multiple files > together so they load as one module/compartment. This must be done with care > because there could be things like file-level symbol collisions. > > I requested named compartments in bug 807205. In summary, there are some > large JS services (like Sync and Firefox Health Report) that consist of a > large number of JSMs. The memory overhead quickly amounts to several hundred > kb, possibly into the MBs. All modules are used together and their primary > use case is the feature they are written for. If e.g. the Sync XPCOM service > could create a "sync" compartment and proceed to import all these modules > there, that would significantly curtail both perf impacts of using multiple > JSMs. > > Another scenario worth mentioning is the shared generic service JSM. For > example, I recently wrote Sqlite.jsm. It contains a promise-based API on top > of Storage/SQLite that makes interacting with SQLite much, much more > pleasant. While it is only currently used for Firefox Health Report, > presumably other users of SQLite will start using it because of its > friendlier API. If we load these generic modules into their own and only > their own compartments, we still have overhead of objects traversing > compartment boundaries. In the case of Sqlite.jsm, that could be SQL query > results. For something like RESTRequest (a generic necko-based HTTP client > library), that's HTTP request and response bodies. These are not trivial, > limited use compartment crossings! In the case of bug 806087, we saw > hundreds of megabytes in allocations. I suppose one solution would be to > allow separate JSMs instances in separate compartments. There will be some > redundancy. But, this should be cancelled out by eliminating > cross-compartment overhead (at least for heavy use modules). > > Those are just my ideas. I'm not a Platform dev. I'm sure some of the ideas > are just plain silly. I know there are ideas I haven't thought of. > > What do you think? Can we solve this problem? > > Gregory > _______________________________________________ > dev-platform mailing list > [email protected] > https://lists.mozilla.org/listinfo/dev-platform _______________________________________________ dev-platform mailing list [email protected] https://lists.mozilla.org/listinfo/dev-platform

