LCOV - app.info - dom/base/nsWindowMemoryReporter.cpp

LCOV - code coverage report
| Current view: | directory - dom/base - nsWindowMemoryReporter.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 88 | 24 | 27.3 %
| Date: | 2012-04-21 | Functions: | 12 | 7 | 58.3 %

           1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
           2                 : /* ***** BEGIN LICENSE BLOCK *****
           3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           4                 :  *
           5                 :  * The contents of this file are subject to the Mozilla Public License Version
           6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           7                 :  * the License. You may obtain a copy of the License at
           8                 :  * http://www.mozilla.org/MPL/
           9                 :  *
          10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          12                 :  * for the specific language governing rights and limitations under the
          13                 :  * License.
          14                 :  *
          15                 :  * The Original Code is Mozilla code.
          16                 :  *
          17                 :  * The Initial Developer of the Original Code is Mozilla Foundation
          18                 :  * Portions created by the Initial Developer are Copyright (C) 2011
          19                 :  * the Initial Developer. All Rights Reserved.
          20                 :  *
          21                 :  * Contributor(s):
          22                 :  *   Mounir Lamouri <mounir.lamouri@mozilla.com> (original author)
          23                 :  *
          24                 :  * Alternatively, the contents of this file may be used under the terms of
          25                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
          26                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          28                 :  * of those above. If you wish to allow use of your version of this file only
          29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          30                 :  * use your version of this file under the terms of the MPL, indicate your
          31                 :  * decision by deleting the provisions above and replace them with the notice
          32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          33                 :  * the provisions above, a recipient may use your version of this file under
          34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          35                 :  *
          36                 :  * ***** END LICENSE BLOCK ***** */
          37                 :
          38                 : #include "nsWindowMemoryReporter.h"
          39                 : #include "nsGlobalWindow.h"
          40                 :
          41                 :
          42            1365 : nsWindowMemoryReporter::nsWindowMemoryReporter()
          43                 : {
          44            1365 : }
          45                 :
          46            4125 : NS_IMPL_ISUPPORTS1(nsWindowMemoryReporter, nsIMemoryMultiReporter)
          47                 :
          48                 : /* static */
          49                 : void
          50            1365 : nsWindowMemoryReporter::Init()
          51                 : {
          52                 :   // The memory reporter manager is going to own this object.
          53            1365 :   NS_RegisterMemoryMultiReporter(new nsWindowMemoryReporter());
          54            1365 : }
          55                 :
          56                 : static bool
          57               0 : AppendWindowURI(nsGlobalWindow *aWindow, nsACString& aStr)
          58                 : {
          59               0 :   nsCOMPtr<nsIDocument> doc = do_QueryInterface(aWindow->GetExtantDocument());
          60               0 :   nsCOMPtr<nsIURI> uri;
          61                 :
          62               0 :   if (doc) {
          63               0 :     uri = doc->GetDocumentURI();
          64                 :   }
          65                 :
          66               0 :   if (!uri) {
          67               0 :     nsIPrincipal *principal = aWindow->GetPrincipal();
          68                 :
          69               0 :     if (principal) {
          70               0 :       principal->GetURI(getter_AddRefs(uri));
          71                 :     }
          72                 :   }
          73                 :
          74               0 :   if (!uri) {
          75               0 :     return false;
          76                 :   }
          77                 :
          78               0 :   nsCString spec;
          79               0 :   uri->GetSpec(spec);
          80                 :
          81                 :   // A hack: replace forward slashes with '\\' so they aren't
          82                 :   // treated as path separators.  Users of the reporters
          83                 :   // (such as about:memory) have to undo this change.
          84               0 :   spec.ReplaceChar('/', '\\');
          85                 :
          86               0 :   aStr += spec;
          87                 :
          88               0 :   return true;
          89                 : }
          90                 :
          91               0 : NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(DOMStyleMallocSizeOf, "windows")
          92                 :
          93                 : static nsresult
          94               0 : CollectWindowReports(nsGlobalWindow *aWindow,
          95                 :                      nsWindowSizes *aWindowTotalSizes,
          96                 :                      nsIMemoryMultiReporterCallback *aCb,
          97                 :                      nsISupports *aClosure)
          98                 : {
          99                 :   // DOM window objects fall into one of three categories:
         100                 :   // - "active" windows are currently either displayed in an active
         101                 :   //   tab, or a child of such a window.
         102                 :   // - "cached" windows are in the fastback cache.
         103                 :   // - "other" windows are closed (or navigated away from w/o being
         104                 :   //   cached) yet held alive by either a website or our code. The
         105                 :   //   latter case may be a memory leak, but not necessarily.
         106                 :   //
         107                 :   // For inner windows we show how much memory the window and its
         108                 :   // document etc use, and we report those per URI, where the URI is
         109                 :   // the document URI, if available, or the codebase of the principal
         110                 :   // in the window. In the case where we're unable to find a URI we're
         111                 :   // dealing with a chrome window with no document in it (or
         112                 :   // somesuch), and for that we make the URI be the string "[system]".
         113                 :   //
         114                 :   // For outer windows we simply group them all together and just show
         115                 :   // the combined count and amount of memory used, which is generally
         116                 :   // a constant amount per window (since all the actual data lives in
         117                 :   // the inner window).
         118                 :   //
         119                 :   // The path we give to the reporter callback for inner windows are
         120                 :   // as follows:
         121                 :   //
         122                 :   //   explicit/window-objects/<category>/top=<top-outer-id> (inner=<top-inner-id>)/inner-window(id=<id>, uri=<uri>)
         123                 :   //
         124                 :   // Where:
         125                 :   // - <category> is active, cached, or other, as described above.
         126                 :   // - <top-outer-id> is the window id (nsPIDOMWindow::WindowID()) of
         127                 :   //   the top outer window (i.e. tab, or top level chrome window).
         128                 :   // - <top-inner-id> is the window id of the top window's inner
         129                 :   //   window.
         130                 :   // - <id> is the window id of the inner window in question.
         131                 :   // - <uri> is the URI per above description.
         132                 :   //
         133                 :   // Exposing the window ids is done to get logical grouping in
         134                 :   // about:memory, and also for debuggability since one can get to the
         135                 :   // nsGlobalWindow for a window id by calling the static method
         136                 :   // nsGlobalWindow::GetInnerWindowWithId(id) (or
         137                 :   // GetOuterWindowWithId(id) in a debugger.
         138                 :   //
         139                 :   // For outer windows we simply use:
         140                 :   //
         141                 :   //   explicit/window-objects/<category>/outer-windows
         142                 :   //
         143                 :   // Which gives us simple counts of how many outer windows (and their
         144                 :   // combined sizes) per category.
         145                 :
         146               0 :   nsCAutoString windowPath("explicit/window-objects/");
         147                 :
         148               0 :   nsIDocShell *docShell = aWindow->GetDocShell();
         149                 :
         150               0 :   nsGlobalWindow *top = aWindow->GetTop();
         151               0 :   nsWindowSizes windowSizes(DOMStyleMallocSizeOf);
         152               0 :   aWindow->SizeOfIncludingThis(&windowSizes);
         153                 :
         154               0 :   if (docShell && aWindow->IsFrozen()) {
         155               0 :     windowPath += NS_LITERAL_CSTRING("cached/");
         156               0 :   } else if (docShell) {
         157               0 :     windowPath += NS_LITERAL_CSTRING("active/");
         158                 :   } else {
         159               0 :     windowPath += NS_LITERAL_CSTRING("other/");
         160                 :   }
         161                 :
         162               0 :   if (aWindow->IsInnerWindow()) {
         163               0 :     windowPath += NS_LITERAL_CSTRING("top=");
         164                 :
         165               0 :     if (top) {
         166               0 :       windowPath.AppendInt(top->WindowID());
         167                 :
         168               0 :       nsGlobalWindow *topInner = top->GetCurrentInnerWindowInternal();
         169               0 :       if (topInner) {
         170               0 :         windowPath += NS_LITERAL_CSTRING(" (inner=");
         171               0 :         windowPath.AppendInt(topInner->WindowID());
         172               0 :         windowPath += NS_LITERAL_CSTRING(")");
         173                 :       }
         174                 :     } else {
         175               0 :       windowPath += NS_LITERAL_CSTRING("none");
         176                 :     }
         177                 :
         178               0 :     windowPath += NS_LITERAL_CSTRING("/inner-window(id=");
         179               0 :     windowPath.AppendInt(aWindow->WindowID());
         180               0 :     windowPath += NS_LITERAL_CSTRING(", uri=");
         181                 :
         182               0 :     if (!AppendWindowURI(aWindow, windowPath)) {
         183               0 :       windowPath += NS_LITERAL_CSTRING("[system]");
         184                 :     }
         185                 :
         186               0 :     windowPath += NS_LITERAL_CSTRING(")");
         187                 :   } else {
         188                 :     // Combine all outer windows per section (active/cached/other) as
         189                 :     // they basically never contain anything of interest, and are
         190                 :     // always pretty much the same size.
         191                 :
         192               0 :     windowPath += NS_LITERAL_CSTRING("outer-windows");
         193                 :   }
         194                 :
         195                 : #define REPORT(_path1, _path2, _amount, _desc)                                \
         196                 :   do {                                                                        \
         197                 :     if (_amount > 0) {                                                        \
         198                 :         nsCAutoString path(_path1);                                           \
         199                 :         path += _path2;                                                       \
         200                 :         nsresult rv;                                                          \
         201                 :         rv = aCb->Callback(EmptyCString(), path, nsIMemoryReporter::KIND_HEAP,\
         202                 :                       nsIMemoryReporter::UNITS_BYTES, _amount,                \
         203                 :                       NS_LITERAL_CSTRING(_desc), aClosure);                   \
         204                 :         NS_ENSURE_SUCCESS(rv, rv);                                            \
         205                 :     }                                                                         \
         206                 :   } while (0)
         207                 :
         208               0 :   REPORT(windowPath, "/dom", windowSizes.mDOM,
         209                 :          "Memory used by a window and the DOM within it.");
         210               0 :   aWindowTotalSizes->mDOM += windowSizes.mDOM;
         211                 :
         212               0 :   REPORT(windowPath, "/style-sheets", windowSizes.mStyleSheets,
         213                 :          "Memory used by style sheets within a window.");
         214               0 :   aWindowTotalSizes->mStyleSheets += windowSizes.mStyleSheets;
         215                 :
         216               0 :   REPORT(windowPath, "/layout/arenas", windowSizes.mLayoutArenas,
         217                 :          "Memory used by layout PresShell, PresContext, and other related "
         218                 :          "areas within a window.");
         219               0 :   aWindowTotalSizes->mLayoutArenas += windowSizes.mLayoutArenas;
         220                 :
         221               0 :   REPORT(windowPath, "/layout/style-sets", windowSizes.mLayoutStyleSets,
         222                 :          "Memory used by style sets within a window.");
         223               0 :   aWindowTotalSizes->mLayoutStyleSets += windowSizes.mLayoutStyleSets;
         224                 :
         225               0 :   REPORT(windowPath, "/layout/text-runs", windowSizes.mLayoutTextRuns,
         226                 :          "Memory used for text-runs (glyph layout) in the PresShell's frame "
         227                 :          "tree, within a window.");
         228               0 :   aWindowTotalSizes->mLayoutTextRuns += windowSizes.mLayoutTextRuns;
         229                 :
         230                 : #undef REPORT
         231                 :
         232               0 :   return NS_OK;
         233                 : }
         234                 :
         235                 : typedef nsTArray< nsRefPtr<nsGlobalWindow> > WindowArray;
         236                 :
         237                 : static
         238                 : PLDHashOperator
         239               0 : GetWindows(const PRUint64& aId, nsGlobalWindow*& aWindow, void* aClosure)
         240                 : {
         241               0 :   ((WindowArray *)aClosure)->AppendElement(aWindow);
         242                 :
         243               0 :   return PL_DHASH_NEXT;
         244                 : }
         245                 :
         246                 : NS_IMETHODIMP
         247               0 : nsWindowMemoryReporter::GetName(nsACString &aName)
         248                 : {
         249               0 :   aName.AssignLiteral("window-objects");
         250               0 :   return NS_OK;
         251                 : }
         252                 :
         253                 : NS_IMETHODIMP
         254               3 : nsWindowMemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb,
         255                 :                                        nsISupports* aClosure)
         256                 : {
         257                 :   nsGlobalWindow::WindowByIdTable* windowsById =
         258               3 :     nsGlobalWindow::GetWindowsTable();
         259               3 :   NS_ENSURE_TRUE(windowsById, NS_OK);
         260                 :
         261                 :   // Hold on to every window in memory so that window objects can't be
         262                 :   // destroyed while we're calling the memory reporter callback.
         263               6 :   WindowArray windows;
         264               3 :   windowsById->Enumerate(GetWindows, &windows);
         265                 :
         266                 :   // Collect window memory usage.
         267               3 :   nsRefPtr<nsGlobalWindow> *w = windows.Elements();
         268               3 :   nsRefPtr<nsGlobalWindow> *end = w + windows.Length();
         269               3 :   nsWindowSizes windowTotalSizes(NULL);
         270               3 :   for (; w != end; ++w) {
         271               0 :     nsresult rv = CollectWindowReports(*w, &windowTotalSizes, aCb, aClosure);
         272               0 :     NS_ENSURE_SUCCESS(rv, rv);
         273                 :   }
         274                 :
         275                 : #define REPORT(_path, _amount, _desc)                                         \
         276                 :   do {                                                                        \
         277                 :     nsresult rv;                                                              \
         278                 :     rv = aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path),             \
         279                 :                        nsIMemoryReporter::KIND_OTHER,                         \
         280                 :                        nsIMemoryReporter::UNITS_BYTES, _amount,               \
         281                 :                        NS_LITERAL_CSTRING(_desc), aClosure);                  \
         282                 :     NS_ENSURE_SUCCESS(rv, rv);                                                \
         283                 :   } while (0)
         284                 :
         285               3 :   REPORT("window-objects-dom", windowTotalSizes.mDOM,
         286                 :          "Memory used for the DOM within windows. "
         287                 :          "This is the sum of all windows' 'dom' numbers.");
         288                 :
         289               3 :   REPORT("window-objects-style-sheets", windowTotalSizes.mStyleSheets,
         290                 :          "Memory used for style sheets within windows. "
         291                 :          "This is the sum of all windows' 'style-sheets' numbers.");
         292                 :
         293               3 :   REPORT("window-objects-layout-arenas", windowTotalSizes.mLayoutArenas,
         294                 :          "Memory used by layout PresShell, PresContext, and other related "
         295                 :          "areas within windows. This is the sum of all windows' "
         296                 :          "'layout/arenas' numbers.");
         297                 :
         298               3 :   REPORT("window-objects-layout-style-sets", windowTotalSizes.mLayoutStyleSets,
         299                 :          "Memory used for style sets within windows. "
         300                 :          "This is the sum of all windows' 'layout/style-sets' numbers.");
         301                 :
         302               3 :   REPORT("window-objects-layout-text-runs", windowTotalSizes.mLayoutTextRuns,
         303                 :          "Memory used for text runs within windows. "
         304                 :          "This is the sum of all windows' 'layout/text-runs' numbers.");
         305                 :
         306                 : #undef REPORT
         307                 :
         308               3 :   return NS_OK;
         309                 : }
         310                 :
         311                 : NS_IMETHODIMP
         312               3 : nsWindowMemoryReporter::GetExplicitNonHeap(PRInt64* aAmount)
         313                 : {
         314                 :   // This reporter only measures heap memory.
         315               3 :   *aAmount = 0;
         316               3 :   return NS_OK;
         317                 : }
         318                 :
         319                 :

Generated by: LCOV version 1.7