Closed
Bug 744311
Opened 13 years ago
Closed 13 years ago
Don't use -1 to represent "unknown" in memory reporters
Categories
(Core :: XPCOM, defect)
Core
XPCOM
Tracking
()
RESOLVED
FIXED
mozilla15
People
(Reporter: n.nethercote, Assigned: n.nethercote)
Details
Attachments
(2 files, 1 obsolete file)
22.26 KB,
patch
|
justin.lebar+bug
:
review+
|
Details | Diff | Splinter Review |
57.68 KB,
patch
|
justin.lebar+bug
:
review+
|
Details | Diff | Splinter Review |
This patch just does trivial stuff as general clean-up and in preparation
for the next patch, e.g.:
- Moves code around in nsMemoryReporterManager.cpp.
- Changes 2-space indenting to 4-space in nsMemoryReporterManager to match
the rest of the file.
- Makes the indenting of NS_MEMORY_REPORTER_IMPLEMENT macros more consistent
throughout the codebase.
Attachment #613872 -
Flags: review?(justin.lebar+bug)
![]() |
Assignee | |
Comment 1•13 years ago
|
||
This patch gets rid of the convention where we use (PRInt64)-1 for the
result of a memory reporter that fails. This makes the code cleaner in a
few places, and allows for future memory reporters that might want to return
negative numbers legitimately. There are two replacement behaviours.
- For reporters that aren't supported on a particular platform, we now avoid
registering them, and handle their absence in various ways.
- For reporters that might fail if something weird happens, we now use the
usual NS_ERROR_* values.
Specific changes of note in the patch:
- aboutMemory.js became a bit simpler. It's also more careful about putting
all memory reporter property accesses (which might throw) within a try
block.
- A new macro, NS_FALLIBLE_MEMORY_REPORTER_IMPLEMENT, is used for
implementing fallible reporters, such as the ones that query the OS.
- nsMemoryReporterManager.cpp minimizes the number of platform-specific
#ifdefs by #defining values that indicate which reporters are implemented
(e.g. HAVE_PAGE_FAULT_REPORTERS), and reusing them later in the file.
Attachment #613873 -
Flags: review?(justin.lebar+bug)
![]() |
Assignee | |
Comment 2•13 years ago
|
||
There was some test bustage on --enable-trace-malloc builds (e.g. the debug builds on the test machines) because |mgr.explicit| throws in that configuration, due to the lack of a "heap-allocated" report. This version handles that.
Attachment #613873 -
Attachment is obsolete: true
Attachment #613873 -
Flags: review?(justin.lebar+bug)
Attachment #614259 -
Flags: review?(justin.lebar+bug)
Comment 3•13 years ago
|
||
Comment on attachment 613872 [details] [diff] [review]
patch 1: trivial preliminary stuff
>+static PRInt64 GetExplicit()
>+{
>+ nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
While we're being anal about whitespace, linebreak after "="?
Updated•13 years ago
|
Attachment #613872 -
Flags: review?(justin.lebar+bug) → review+
Comment 4•13 years ago
|
||
> [This] allows for future memory reporters that might want to return
> negative numbers legitimately.
What might this be used for?
![]() |
Assignee | |
Comment 5•13 years ago
|
||
> What might this be used for?
Changes that could be negative. When I was reducing the memory consumption of about:memory I was vaguely envisioning some reporters that measured the change in resident since the last time the reporters ran, or something like that.
Even if we can't image such a case, I still like this change for the fact that it gets rid of the non-standard error case (-1) and replaces it with the standard one (nsresult).
Comment 6•13 years ago
|
||
Do you have a use case in mind for GetPath() or GetUnits() failing? It's not clear to me that it's useful to consider these fallible.
Comment 7•13 years ago
|
||
>diff --git a/toolkit/components/aboutmemory/content/aboutMemory.js b/toolkit/components/aboutmemory/content/aboutMemory.js
>--- a/toolkit/components/aboutmemory/content/aboutMemory.js
>+++ b/toolkit/components/aboutmemory/content/aboutMemory.js
>+ catch (ex) {
>+ // There are two exception cases that must be distinguished here.
>+ //
>+ // - We want to halt proceedings on exceptions thrown within this file
>+ // (i.e. assertion failures in handleReport); such exceptions contain
>+ // gAssertionFailureMsgPrefix in their string representation.
>+ //
>+ // - We want to continue on when faced with exceptions thrown outside
>+ // this file (i.e. in collectReports).
Maybe "(e.g. when reading a memory reporter's amount)"? That happens to occur during collectReports, but that's not the important part.
>diff --git a/toolkit/components/telemetry/TelemetryPing.js b/toolkit/components/telemetry/TelemetryPing.js
>--- a/toolkit/components/telemetry/TelemetryPing.js
>+++ b/toolkit/components/telemetry/TelemetryPing.js
>@@ -365,53 +365,60 @@ TelemetryPing.prototype = {
> } catch (e) {
> // OK to skip memory reporters in xpcshell
> return;
> }
>
> let e = mgr.enumerateReporters();
> while (e.hasMoreElements()) {
> let mr = e.getNext().QueryInterface(Ci.nsIMemoryReporter);
>- let id = MEM_HISTOGRAMS[mr.path];
>+ let mrPath, mrAmount, mrUnits;
>+ try {
>+ mrPath = mr.path;
>+ } catch (e) {
>+ continue;
>+ }
>+ let id = MEM_HISTOGRAMS[mrPath];
> if (!id) {
> continue;
> }
>- // mr.amount is expensive to read in some cases, so get it only once.
>- let amount = mr.amount;
>- if (amount == -1) {
>+ try {
>+ mrAmount = mr.amount;
>+ mrUnits = mr.units;
I'm not convinced there's a benefit to assuming that mr.units and mr.path can fail.
>diff --git a/xpcom/base/nsMemoryReporterManager.cpp b/xpcom/base/nsMemoryReporterManager.cpp
>--- a/xpcom/base/nsMemoryReporterManager.cpp
>+++ b/xpcom/base/nsMemoryReporterManager.cpp
>-static PRInt64 GetProcSelfStatmField(int n)
>+static nsresult GetProcSelfStatmField(int field, PRInt64 *n)
> {
> // There are more than two fields, but we're only interested in the first
> // two.
> static const int MAX_FIELD = 2;
> size_t fields[MAX_FIELD];
>- NS_ASSERTION(n < MAX_FIELD, "bad field number");
>+ NS_ASSERTION(field < MAX_FIELD, "bad field number");
Would you mind making this MOZ_ASSERT (fatal debug asserrtion, rather than just
a warning), while we're at it?
> FILE *f = fopen("/proc/self/statm", "r");
> if (f) {
> int nread = fscanf(f, "%zu %zu", &fields[0], &fields[1]);
> fclose(f);
>- return (PRInt64) ((nread == MAX_FIELD) ? fields[n]*getpagesize() : -1);
>+ if (nread == MAX_FIELD) {
>+ *n = fields[field] * getpagesize();
>+ return NS_OK;
>+ }
Nit: Whitespace at the end of this line. There's trailing whitespace in a few
other places too; I'd just strip it off the patch before you check in.
>-static PRInt64 GetVsize()
>+#define HAVE_VSIZE_AND_RESIDENT_REPORTERS 1
>+static nsresult GetVsize(PRInt64 *n)
> {
>- PRInt64 Vsize, Resident;
>- XMappingIter(Vsize, Resident);
>- return Vsize;
>+ PRInt64 vsize, resident;
>+ XMappingIter(vsize, resident);
>+ *n = vsize;
>+ return NS_OK;
What if vsize is -1?
>-static PRInt64 GetResident()
>+static nsresult GetResident(PRInt64 *n)
> {
>- PRInt64 Vsize, Resident;
>- XMappingIter(Vsize, Resident);
>- return Resident;
>+ PRInt64 vsize, resident;
>+ XMappingIter(vsize, resident);
>+ *n = resident;
Similarly for resident.
>-static PRInt64 GetPrivate()
>+#define HAVE_PRIVATE_REPORTER
>+static nsresult GetPrivate(PRInt64 *n)
> {
> PROCESS_MEMORY_COUNTERS_EX pmcex;
> pmcex.cb = sizeof(PROCESS_MEMORY_COUNTERS_EX);
>
> if (!GetProcessMemoryInfo(GetCurrentProcess(),
> (PPROCESS_MEMORY_COUNTERS) &pmcex, sizeof(pmcex)))
>- return (PRInt64) -1;
>+ {
>+ return NS_ERROR_FAILURE;
>+ }
I don't care, but you may want to cuddle the brace to match (most of) the rest of the file.
>- return pmcex.PrivateUsage;
>+ *n = pmcex.PrivateUsage;
>+ return NS_OK;
> }
>
>-NS_MEMORY_REPORTER_IMPLEMENT(Private,
>+NS_FALLIBLE_MEMORY_REPORTER_IMPLEMENT(Private,
> "private",
> KIND_OTHER,
> UNITS_BYTES,
> GetPrivate,
> "Memory that cannot be shared with other processes, including memory that "
> "is committed and marked MEM_PRIVATE, data that is not mapped, and "
> "executable pages that have been written to.")
>
>-#else
>+#endif // HAVE_PRIVATE_REPORTER
That's not accurate -- it's #endif for |#elif(XP_WIN)|. Maybe you meant to use the HAVE_PRIVATE_REPORTER define to guard this? I don't care either way, so long as the comment is right.
> static PRInt64 GetHeapCommittedFragmentation()
> {
> jemalloc_stats_t stats;
> jemalloc_stats(&stats);
>- return (PRInt64) 10000 * (1 - stats.allocated / (double)stats.committed);
>+ return 10000 * (1 - stats.allocated / (double)stats.committed);
This doesn't cause a warning?
> static PRInt64 GetHeapDirty()
> {
> jemalloc_stats_t stats;
> jemalloc_stats(&stats);
>- return (PRInt64) stats.dirty;
>+ return stats.dirty;
> }
I think the reason all these PRInt64 casts were there is to make explicit the cast from size_t (unsigned) to PRInt64 (signed). Even if this doesn't warn now, perhaps -Wconversion would generate a warning.
>+#define HAVE_HEAP_ALLOCATED_AND_EXPLICIT_REPORTERS 1
> static PRInt64 GetHeapUnallocated()
> {
> struct mstats stats = mstats();
>- return (PRInt64) (stats.bytes_total - stats.bytes_used);
>+ return stats.bytes_total - stats.bytes_used;
> }
This one in particular might go negative. Are you sure the behavior is right without the cast (or even, with it?).
I guess I should polish up on my C++ casting rules...
>+#ifdef HAVE_HEAP_ALLOCATED_AND_EXPLICIT_REPORTERS
> NS_MEMORY_REPORTER_IMPLEMENT(HeapUnallocated,
> "heap-unallocated",
> KIND_OTHER,
> UNITS_BYTES,
> GetHeapUnallocated,
> "Memory mapped by the heap allocator that is not part of an active "
>- "allocation. Much of this memory may be uncommitted -- that is, it does not "
>- "take up space in physical memory or in the swap file.")
>+ "allocation. Much of this memory may be uncommitted -- that is, it does "
>+ "not take up space in physical memory or in the swap file.")
>
> NS_MEMORY_REPORTER_IMPLEMENT(HeapAllocated,
> "heap-allocated",
> KIND_OTHER,
> UNITS_BYTES,
> GetHeapAllocated,
> "Memory mapped by the heap allocator that is currently allocated to the "
> "application. This may exceed the amount of memory requested by the "
> "application because the allocator regularly rounds up request sizes. (The "
> "exact amount requested is not recorded.)")
>
>-static PRInt64 GetExplicit()
>+// The computation of "explicit" fails if "heap-allocated" isn't available,
>+// which is why this is depends on HAVE_HEAP_ALLOCATED_AND_EXPLICIT_REPORTERS.
Shouldn't we have a HAVE_HEAP_ALLOCATED_REPORTER define, and then a separate HAVE_EXPLICIT define? Seems kind of weird to say "we have jemalloc, therefore we have explicit".
> NS_IMETHODIMP
> nsMemoryReporterManager::GetResident(PRInt64 *aResident)
> {
>- *aResident = ::GetResident();
>- return NS_OK;
>+#if HAVE_VSIZE_AND_RESIDENT_REPORTERS
>+ return ::GetResident(aResident);
>+#else
>+ *aResident = 0;
>+ return NS_ERROR_NOT_IMPLEMENTED;
Do you think NS_ERROR_NOT_AVAILABLE would be better?
>@@ -812,20 +816,21 @@ nsMemoryReporterManager::GetExplicit(PRI
> if (explicitNonHeapMultiSize != explicitNonHeapMultiSize2) {
> char *msg = PR_smprintf("The two measurements of 'explicit' memory "
> "usage don't match (%lld vs %lld)",
> explicitNonHeapMultiSize,
> explicitNonHeapMultiSize2);
> NS_WARNING(msg);
> PR_smprintf_free(msg);
FYI (you don't have to change this), you could use nsPrintfCString here instead:
NS_WARNING(nsPrintfCString(128, "%lld", explicitNonHeapMultiSize).get());
Soon, you won't even need to specify a size in the PrintfCString, which will be nice...
Comment 8•13 years ago
|
||
Comment on attachment 614259 [details] [diff] [review]
patch 2, v2: the interesting bits
r=me, but there are some little things we need to clear up.
Attachment #614259 -
Flags: review?(justin.lebar+bug) → review+
![]() |
Assignee | |
Comment 9•13 years ago
|
||
Comment 10•13 years ago
|
||
https://hg.mozilla.org/mozilla-central/rev/1a38b48816c9
https://hg.mozilla.org/mozilla-central/rev/62fc36c0317d
Status: ASSIGNED → RESOLVED
Closed: 13 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla15
You need to log in
before you can comment on or make changes to this bug.
Description
•