Exemplo n.º 1
0
static void
CollectWindowReports(nsGlobalWindow *aWindow,
                     WindowTotals *aWindowTotals,
                     nsIMemoryMultiReporterCallback *aCb,
                     nsISupports *aClosure)
{
  // DOM window objects fall into one of three categories:
  // - "active" windows are currently either displayed in an active
  //   tab, or a child of such a window.
  // - "cached" windows are in the fastback cache.
  // - "other" windows are closed (or navigated away from w/o being
  //   cached) yet held alive by either a website or our code. The
  //   latter case may be a memory leak, but not necessarily.
  //
  // For inner windows we show how much memory the window and its
  // document etc use, and we report those per URI, where the URI is
  // the document URI, if available, or the codebase of the principal
  // in the window. In the case where we're unable to find a URI we're
  // dealing with a chrome window with no document in it (or
  // somesuch), and for that we make the URI be the string "[system]".
  //
  // For outer windows we simply group them all together and just show
  // the combined count and amount of memory used, which is generally
  // a constant amount per window (since all the actual data lives in
  // the inner window).
  //
  // The path we give to the reporter callback for inner windows are
  // as follows:
  //
  //   explicit/dom+style/window-objects/<category>/top=<top-outer-id> (inner=<top-inner-id>)/inner-window(id=<id>, uri=<uri>)
  //
  // Where:
  // - <category> is active, cached, or other, as described above.
  // - <top-outer-id> is the window id (nsPIDOMWindow::WindowID()) of
  //   the top outer window (i.e. tab, or top level chrome window).
  // - <top-inner-id> is the window id of the top window's inner
  //   window.
  // - <id> is the window id of the inner window in question.
  // - <uri> is the URI per above description.
  //
  // Exposing the window ids is done to get logical grouping in
  // about:memory, and also for debuggability since one can get to the
  // nsGlobalWindow for a window id by calling the static method
  // nsGlobalWindow::GetInnerWindowWithId(id) (or
  // GetOuterWindowWithId(id) in a debugger.
  //
  // For outer windows we simply use:
  // 
  //   explicit/dom+style/window-objects/<category>/outer-windows
  //
  // Which gives us simple counts of how many outer windows (and their
  // combined sizes) per category.

  nsCAutoString windowPath("explicit/dom+style/window-objects/");

  nsIDocShell *docShell = aWindow->GetDocShell();

  nsGlobalWindow *top = aWindow->GetTop();
  PRInt64 windowDOMSize = aWindow->SizeOf();
  PRInt64 styleSheetsSize = aWindow->SizeOfStyleSheets(WindowStyleSheetsMallocSizeOf);

  if (docShell && aWindow->IsFrozen()) {
    windowPath += NS_LITERAL_CSTRING("cached/");
  } else if (docShell) {
    windowPath += NS_LITERAL_CSTRING("active/");
  } else {
    windowPath += NS_LITERAL_CSTRING("other/");
  }

  if (aWindow->IsInnerWindow()) {
    windowPath += NS_LITERAL_CSTRING("top=");

    if (top) {
      windowPath.AppendInt(top->WindowID());

      nsGlobalWindow *topInner = top->GetCurrentInnerWindowInternal();
      if (topInner) {
        windowPath += NS_LITERAL_CSTRING(" (inner=");
        windowPath.AppendInt(topInner->WindowID());
        windowPath += NS_LITERAL_CSTRING(")");
      }
    } else {
      windowPath += NS_LITERAL_CSTRING("none");
    }

    windowPath += NS_LITERAL_CSTRING("/inner-window(id=");
    windowPath.AppendInt(aWindow->WindowID());
    windowPath += NS_LITERAL_CSTRING(", uri=");

    if (!AppendWindowURI(aWindow, windowPath)) {
      windowPath += NS_LITERAL_CSTRING("[system]");
    }

    windowPath += NS_LITERAL_CSTRING(")");
  } else {
    // Combine all outer windows per section (active/cached/other) as
    // they basically never contain anything of interest, and are
    // always pretty much the same size.

    windowPath += NS_LITERAL_CSTRING("outer-windows");
  }

  if (windowDOMSize > 0) {
    nsCAutoString domPath(windowPath);
    domPath += "/dom";
    NS_NAMED_LITERAL_CSTRING(kWindowDesc,
                             "Memory used by a window and the DOM within it.");
    aCb->Callback(EmptyCString(), domPath, nsIMemoryReporter::KIND_HEAP,
                  nsIMemoryReporter::UNITS_BYTES, windowDOMSize, kWindowDesc,
                  aClosure);
    aWindowTotals->mDom += windowDOMSize;
  }

  if (styleSheetsSize > 0) {
    nsCAutoString styleSheetsPath(windowPath);
    styleSheetsPath += "/style-sheets";
    NS_NAMED_LITERAL_CSTRING(kStyleSheetsDesc,
                             "Memory used by style sheets within a window.");
    aCb->Callback(EmptyCString(), styleSheetsPath,
                  nsIMemoryReporter::KIND_HEAP,
                  nsIMemoryReporter::UNITS_BYTES, styleSheetsSize,
                  kStyleSheetsDesc, aClosure);
    aWindowTotals->mStyleSheets += styleSheetsSize;
  }
}
static void
CollectWindowReports(nsGlobalWindow *aWindow,
                     nsWindowSizes *aWindowTotalSizes,
                     nsIMemoryMultiReporterCallback *aCb,
                     nsISupports *aClosure)
{
  // DOM window objects fall into one of three categories:
  // - "active" windows are currently either displayed in an active
  //   tab, or a child of such a window.
  // - "cached" windows are in the fastback cache.
  // - "other" windows are closed (or navigated away from w/o being
  //   cached) yet held alive by either a website or our code. The
  //   latter case may be a memory leak, but not necessarily.
  //
  // For inner windows we show how much memory the window and its
  // document etc use, and we report those per URI, where the URI is
  // the document URI, if available, or the codebase of the principal
  // in the window. In the case where we're unable to find a URI we're
  // dealing with a chrome window with no document in it (or
  // somesuch), and for that we make the URI be the string "[system]".
  //
  // For outer windows we simply group them all together and just show
  // the combined count and amount of memory used, which is generally
  // a constant amount per window (since all the actual data lives in
  // the inner window).
  //
  // The path we give to the reporter callback for inner windows are
  // as follows:
  //
  //   explicit/window-objects/<category>/top=<top-outer-id> (inner=<top-inner-id>)/inner-window(id=<id>, uri=<uri>)
  //
  // Where:
  // - <category> is active, cached, or other, as described above.
  // - <top-outer-id> is the window id (nsPIDOMWindow::WindowID()) of
  //   the top outer window (i.e. tab, or top level chrome window).
  // - <top-inner-id> is the window id of the top window's inner
  //   window.
  // - <id> is the window id of the inner window in question.
  // - <uri> is the URI per above description.
  //
  // Exposing the window ids is done to get logical grouping in
  // about:memory, and also for debuggability since one can get to the
  // nsGlobalWindow for a window id by calling the static method
  // nsGlobalWindow::GetInnerWindowWithId(id) (or
  // GetOuterWindowWithId(id) in a debugger.
  //
  // For outer windows we simply use:
  // 
  //   explicit/window-objects/<category>/outer-windows
  //
  // Which gives us simple counts of how many outer windows (and their
  // combined sizes) per category.

  nsCAutoString windowPath("explicit/window-objects/");

  nsIDocShell *docShell = aWindow->GetDocShell();

  nsGlobalWindow *top = aWindow->GetTop();
  nsWindowSizes windowSizes(DOMStyleMallocSizeOf);
  aWindow->SizeOfIncludingThis(&windowSizes);

  if (docShell && aWindow->IsFrozen()) {
    windowPath += NS_LITERAL_CSTRING("cached/");
  } else if (docShell) {
    windowPath += NS_LITERAL_CSTRING("active/");
  } else {
    windowPath += NS_LITERAL_CSTRING("other/");
  }

  if (aWindow->IsInnerWindow()) {
    windowPath += NS_LITERAL_CSTRING("top=");

    if (top) {
      windowPath.AppendInt(top->WindowID());

      nsGlobalWindow *topInner = top->GetCurrentInnerWindowInternal();
      if (topInner) {
        windowPath += NS_LITERAL_CSTRING(" (inner=");
        windowPath.AppendInt(topInner->WindowID());
        windowPath += NS_LITERAL_CSTRING(")");
      }
    } else {
      windowPath += NS_LITERAL_CSTRING("none");
    }

    windowPath += NS_LITERAL_CSTRING("/inner-window(id=");
    windowPath.AppendInt(aWindow->WindowID());
    windowPath += NS_LITERAL_CSTRING(", uri=");

    if (!AppendWindowURI(aWindow, windowPath)) {
      windowPath += NS_LITERAL_CSTRING("[system]");
    }

    windowPath += NS_LITERAL_CSTRING(")");
  } else {
    // Combine all outer windows per section (active/cached/other) as
    // they basically never contain anything of interest, and are
    // always pretty much the same size.

    windowPath += NS_LITERAL_CSTRING("outer-windows");
  }

#define REPORT(_path1, _path2, _amount, _desc)                                \
  do {                                                                        \
    if (_amount > 0) {                                                        \
        nsCAutoString path(_path1);                                           \
        path += _path2;                                                       \
        aCb->Callback(EmptyCString(), path, nsIMemoryReporter::KIND_HEAP,     \
                      nsIMemoryReporter::UNITS_BYTES, _amount,                \
                      NS_LITERAL_CSTRING(_desc), aClosure);                   \
    }                                                                         \
  } while (0)

  REPORT(windowPath, "/dom", windowSizes.mDOM,
         "Memory used by a window and the DOM within it.");
  aWindowTotalSizes->mDOM += windowSizes.mDOM;

  REPORT(windowPath, "/style-sheets", windowSizes.mStyleSheets,
         "Memory used by style sheets within a window.");
  aWindowTotalSizes->mStyleSheets += windowSizes.mStyleSheets;

  REPORT(windowPath, "/layout/arenas", windowSizes.mLayoutArenas,
         "Memory used by layout PresShell, PresContext, and other related "
         "areas within a window.");
  aWindowTotalSizes->mLayoutArenas += windowSizes.mLayoutArenas;

  REPORT(windowPath, "/layout/style-sets", windowSizes.mLayoutStyleSets,
         "Memory used by style sets within a window.");
  aWindowTotalSizes->mLayoutStyleSets += windowSizes.mLayoutStyleSets;

  REPORT(windowPath, "/layout/text-runs", windowSizes.mLayoutTextRuns,
         "Memory used for text-runs (glyph layout) in the PresShell's frame "
         "tree, within a window.");
  aWindowTotalSizes->mLayoutTextRuns += windowSizes.mLayoutTextRuns;

#undef REPORT
}