Closed Bug 676732 Opened 13 years ago Closed 13 years ago

Measure and/or avoid slop in important JS memory reporters

Categories

(Core :: JavaScript Engine, defect)

x86_64
Linux
defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla9

People

(Reporter: n.nethercote, Assigned: n.nethercote)

References

(Blocks 1 open bug)

Details

(Whiteboard: [MemShrink:P2][inbound])

Attachments

(1 file)

The JS reporters should used malloc_usable_size/malloc_size where appropriate. (Actually, all memory reporters should, but JS is a good place to start.) Bug 675136 comment 14 showed that "scripts" under-reports the actual memory used by about 20%, for example.
We don't use mozalloc in JS, so you'll need to copy/tweak this bit: size_t moz_malloc_usable_size(void *ptr) { if (!ptr) return 0; #if defined(MOZ_MEMORY) return malloc_usable_size(ptr); #elif defined(XP_MACOSX) return malloc_size(ptr); #elif defined(XP_WIN) return _msize(ptr); #else return 0; #endif } I'm working on abstracting this in mozalloc so that we always provide a malloc_usable_size symbol, but it will be a while before that makes it near the JS shell at least.
Thanks for the tip. I foresee a JS_malloc_usable_size in my near future.
Oh, but using MOZ_MEMORY in the JS engine doesn't appear to be kosher. That messes with my plans significantly. Hmm.
cjones, do you have any idea about how to do this?
Here's sample output from DMD that shows why this is important, BTW: ==23402== Unreported: 1,950,496 (cumulative: 11,740,992) bytes in 21,897 heap block(s) in record 4 of 11626: ==23402== Requested bytes unreported: 0 / 9,052,832 ==23402== Slop bytes unreported: 1,950,496 / 1,950,496 ==23402== at 0x4029F90: malloc (vg_replace_malloc.c:235) ==23402== by 0x6E6692A: js_malloc (jsutil.h:248) ==23402== by 0x6E66A02: JSRuntime::malloc_(unsigned long, JSContext*) (jscntxt.h:728) ==23402== by 0x6E66B60: JSContext::malloc_(unsigned long) (jscntxt.h:1261) ==23402== by 0x7D0E2C8: JSScript::NewScript(JSContext*, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned i nt, unsigned int, unsigned int, unsigned int, unsigned short, unsigned short, JSVersion) (jsscript.cpp:963) ==23402== by 0x7D0EB19: JSScript::NewScriptFromCG(JSContext*, JSCodeGenerator*) (jsscript.cpp:1145) 9MB are reported, but there's almost 2MB of slop that isn't reported.
Why not just use moz_malloc_usable_size() directly? mozalloc is "lower level" than js/src, it's fine for js/src to use it. Would want a way to turn that off for embedders though.
> Why not just use moz_malloc_usable_size() directly? I can't work out how to do it. I #included "mozilla/mozalloc.h" in jstracer.cpp and got this in a browser build: In file included from /home/njn/moz/mi2/js/src/jstracer.cpp:2511:0: ./../../dist/include/mozilla/mozalloc.h:53:26: fatal error: xpcom-config.h: No such file or directory More generally, #including Gecko headers in the JS engine *really* doesn't feel right. For example, I get the following in a shell build, which is hardly surprising: /home/njn/moz/mi2/js/src/jstracer.cpp:2511:30: fatal error: mozilla/mozalloc.h: No such file or directory My plan B is to do all the moz_malloc_usable_size calls effectively from within xpconnect, either by (a) exposing the relevant heap blocks from the JS engine, or (b) passing in a pointer to moz_malloc_usable_size to various places.
(In reply to Nicholas Nethercote [:njn] from comment #7) > > Why not just use moz_malloc_usable_size() directly? > > I can't work out how to do it. I #included "mozilla/mozalloc.h" in > jstracer.cpp and got this in a browser build: > > In file included from /home/njn/moz/mi2/js/src/jstracer.cpp:2511:0: > ./../../dist/include/mozilla/mozalloc.h:53:26: fatal error: > xpcom-config.h: No such file or directory > mozalloc depends on a few macros written by configure, like NS_ATTR_MALLOC. These are checked by js/src/configure.in too, so the expedient fix here is to make mozalloc use the js config.h (not sure where that lives). Generally, this stuff needs to live in mfbt or a central location, IMHO. > More generally, #including Gecko headers in the JS engine *really* doesn't > feel right. mozalloc isn't gecko, it's lower level. It has the same depedencies as NSPR (i.e. none). In fact, in android builds, NSPR depends on mozalloc (as does SM). > For example, I get the following in a shell build, which is > hardly surprising: > > /home/njn/moz/mi2/js/src/jstracer.cpp:2511:30: fatal error: > mozilla/mozalloc.h: No such file or directory > It's surprising to me! ;) Maybe shell builds aren't jemalloc enabled, so memory/ isn't being built? If so, that's generally bad (would skew performance measurements in the shell).
> Maybe shell builds aren't jemalloc enabled They're not, I just checked.
(In reply to Nicholas Nethercote [:njn] from comment #9) > > Maybe shell builds aren't jemalloc enabled > > They're not, I just checked. Bug 580409.
I took a brief look at how to call moz_malloc_usable_size. There are two ways that jemalloc gets used. For Gecko and similar, mozalloc is #included, which replaces malloc with moz_malloc, which calles jemalloc. For parts of Firefox which don't have this #include, jemalloc does a system specific override of some memory bits. In the shell, neither works, because we don't build memory/, and don't #include mozalloc.h. We need both to use moz_malloc_usable_memory, but there's a few issues to overcome for landing: - we don't want to override new in the engine - we don't want to accidentally pollute embedders code by defining malloc to moz_malloc in something like jsutil.h - we can't rely on xpcom headers - historically, there has been some objection to how we pull the memory/ directory into js/src.
(In reply to Paul Biggar from comment #11) > I took a brief look at how to call moz_malloc_usable_size. > > There are two ways that jemalloc gets used. For Gecko and similar, mozalloc > is #included, which replaces malloc with moz_malloc, which calles jemalloc. moz_malloc() just calls malloc(), which is defined to the jemalloc impl on android and apparently OS X now, and the rest of the time calls the normal system malloc (which is jemalloc on "normal" linux and windows). > For parts of Firefox which don't have this #include, jemalloc does a system > specific override of some memory bits. > That may be true for mac, but otherwise we either do the system-specific override, or (on android) we play linker tricks to make malloc et al. symbols resolve to jemalloc's. > We need both to use moz_malloc_usable_memory, but there's a few issues to > overcome for landing: > > - we don't want to override new in the engine SM uses jsnew()/jsdelete() or something, right? The default operator new throws on OOM, which nobody wants, so I assume SM doesn't use it (IIRC njn added a check for that). Including mozalloc.h as it exists today would mean that njn's check would break, because vanilla operator new would boil away to a call to moz_xmalloc. We could split moz_malloc_usable_memory into its own header, which we do for mozalloc_abort() already. We should probably be using mozalloc_abort() or whatever in js/src too; it stinks maintaining separate copies of the abort-and-trigger-breakpad code. Candidate for mfbt I guess. > - we don't want to accidentally pollute embedders code by defining malloc > to moz_malloc in something like jsutil.h That doesn't happen unless the mozalloc_macro_wrappers.h are included, which has to be done manually. > - historically, there has been some objection to how we pull the memory/ > directory into js/src. js/src depends on top-level mfbt/ already. We accomplish that today by building mfbt/ objects into libmozjs. We could make building memory/ be js/src's responsibility, whether shell or browser build.
Attached patch patchSplinter Review
This patch uses moz_malloc_usable_size for various JS memory reporters in order to measure slop bytes caused by the heap allocator rounding up request sizes. Details: - The memory reporters affected: mjit-data, script-data, object-slots, property-tables, runtime/runtime-object. I modified their descriptions to mention that slop bytes are included in them. - I avoided the difficulties in calling malloc_usable_size (and equivalents) from within the JS engine by passing in a function pointer to moz_malloc_usable_size where necessary. This seemed like the least worst solution. - moz_malloc_usable_size will return 0 on platforms where it can't be implemented, and in that case we fall back to using the existing calculations, which don't account for slop. (Passing in NULL for the function pointer also causes us to fall-back; I do this in one place in the shell.) - These changes account for roughly 3MB of what is currently dark matter when starting the browser and loading Gmail. - I also changed the sizes of the reserve spaces used in TM's three VMAllocators. These new sizes are all sizes that don't have any slop. Making them smaller seems unlikely to cause problems in practice, because they were very conservative (also, I accidentally switched the "test" and "trace" allocator reserve sizes when I introduced them, a botch that this patch fixes). And it reduces TM's memory usage slightly, as well as making the tjit-data/allocators-reserve reporters more accurate.
Attachment #553993 - Flags: review?(dmandelin)
Summary: Use malloc_usable_size in JS memory reporters → Measure and/or avoid slop in important JS memory reporters
Whiteboard: [MemShrink]
Attachment #553993 - Flags: review?(dmandelin) → review+
Depends on: 674251
Whiteboard: [MemShrink] → [MemShrink:P2]
(In reply to Nicholas Nethercote [:njn] from comment #13) > - I avoided the difficulties in calling malloc_usable_size (and equivalents) > from within the JS engine by passing in a function pointer to > moz_malloc_usable_size where necessary. This seemed like the least worst > solution. Why not to add a static pointer that will be set during initialization to moz_malloc_usable_size on platforms where we know that it works?
Whiteboard: [MemShrink:P2] → [MemShrink:P2][inbound]
Not sure if this is noise or not, but supposedly improved dromaeo css :-) https://groups.google.com/forum/#!topic/mozilla.dev.tree-management/fqr58Zlx4Oc
Status: ASSIGNED → RESOLVED
Closed: 13 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla9
(In reply to Ed Morley [:edmorley] from comment #17) > Not sure if this is noise or not, but supposedly improved dromaeo css :-) > https://groups.google.com/forum/#!topic/mozilla.dev.tree-management/ > fqr58Zlx4Oc I'm 99.99% certain that's noise :)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: