bug 1096718 - - display time measured spent in each compartment r=billm,mossop

This commit is contained in:
Brad Lassey 2015-01-13 17:38:05 -08:00
parent 4f66eb5a78
commit 36b059df69
18 changed files with 357 additions and 4 deletions

View File

@ -51,11 +51,10 @@ static RedirEntry kRedirMap[] = {
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::ALLOW_SCRIPT |
nsIAboutModule::HIDE_FROM_ABOUTABOUT },
{ "compartments", "chrome://global/content/aboutCompartments.xhtml",
nsIAboutModule::ALLOW_SCRIPT |
nsIAboutModule::HIDE_FROM_ABOUTABOUT },
{ "memory", "chrome://global/content/aboutMemory.xhtml",
nsIAboutModule::ALLOW_SCRIPT },
{ "compartments", "chrome://global/content/aboutCompartments.xhtml",
nsIAboutModule::ALLOW_SCRIPT },
{ "addons", "chrome://mozapps/content/extensions/extensions.xul",
nsIAboutModule::ALLOW_SCRIPT },
{ "newaddon", "chrome://mozapps/content/extensions/newaddon.xul",

View File

@ -168,6 +168,7 @@ const mozilla::Module::ContractIDEntry kDocShellContracts[] = {
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "neterror", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "compartments", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "memory", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "compartments", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "addons", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "newaddon", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "support", &kNS_ABOUT_REDIRECTOR_MODULE_CID },

View File

@ -167,6 +167,30 @@ JS_GetEmptyString(JSRuntime *rt)
return rt->emptyString;
}
JS_PUBLIC_API(bool)
JS_GetCompartmentStats(JSRuntime *rt, CompartmentStatsVector &stats)
{
if (!stats.resizeUninitialized(rt->numCompartments))
return false;
size_t pos = 0;
for (CompartmentsIter c(rt, WithAtoms); !c.done(); c.next()) {
CompartmentTimeStats *stat = &stats[pos];
stat->time = c.get()->totalTime;
stat->compartment = c.get();
stat->addonId = c.get()->addonId;
if (rt->compartmentNameCallback) {
(*rt->compartmentNameCallback)(rt, stat->compartment,
stat->compartmentName,
MOZ_ARRAY_LENGTH(stat->compartmentName));
} else {
strcpy(stat->compartmentName, "<unknown>");
}
pos++;
}
return true;
}
namespace js {
void

View File

@ -1042,6 +1042,19 @@ JS_GetEmptyStringValue(JSContext *cx);
extern JS_PUBLIC_API(JSString *)
JS_GetEmptyString(JSRuntime *rt);
struct CompartmentTimeStats {
char compartmentName[1024];
JSAddonId *addonId;
JSCompartment *compartment;
uint64_t time; // microseconds
uint64_t cpowTime; // microseconds
};
typedef js::Vector<CompartmentTimeStats, 0, js::SystemAllocPolicy> CompartmentStatsVector;
extern JS_PUBLIC_API(bool)
JS_GetCompartmentStats(JSRuntime *rt, CompartmentStatsVector &stats);
/*
* Format is a string of the following characters (spaces are insignificant),
* specifying the tabulated type conversions:

View File

@ -345,8 +345,16 @@ xpc::TraceXPCGlobal(JSTracer *trc, JSObject *obj)
compartmentPrivate->scope->TraceInside(trc);
}
namespace xpc {
uint64_t
GetCompartmentCPOWMicroseconds(JSCompartment *compartment)
{
xpc::CompartmentPrivate *compartmentPrivate = xpc::CompartmentPrivate::Get(compartment);
return compartmentPrivate ? PR_IntervalToMicroseconds(compartmentPrivate->CPOWTime) : 0;
}
JSObject*
CreateGlobalObject(JSContext *cx, const JSClass *clasp, nsIPrincipal *principal,
JS::CompartmentOptions& aOptions)

View File

@ -139,6 +139,9 @@ XrayAwareCalleeGlobal(JSObject *fun);
void
TraceXPCGlobal(JSTracer *trc, JSObject *obj);
uint64_t
GetCompartmentCPOWMicroseconds(JSCompartment *compartment);
} /* namespace xpc */
namespace JS {

View File

@ -0,0 +1,75 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-*/
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
const { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm", {});
function go() {
let compartmentInfo = Cc["@mozilla.org/compartment-info;1"]
.getService(Ci.nsICompartmentInfo);
let compartments = compartmentInfo.getCompartments();
let count = compartments.length;
let addons = {};
for (let i = 0; i < count; i++) {
let compartment = compartments.queryElementAt(i, Ci.nsICompartment);
if (addons[compartment.addonId]) {
addons[compartment.addonId].time += compartment.time;
addons[compartment.addonId].CPOWTime += compartment.CPOWTime;
addons[compartment.addonId].compartments.push(compartment);
} else {
addons[compartment.addonId] = {
time: compartment.time,
CPOWTime: compartment.CPOWTime,
compartments: [compartment]
};
}
}
let dataDiv = document.getElementById("data");
for (let addon in addons) {
let el = document.createElement("tr");
let name = document.createElement("td");
let time = document.createElement("td");
let cpow = document.createElement("td");
name.className = "addon";
time.className = "time";
cpow.className = "cpow";
name.textContent = addon;
AddonManager.getAddonByID(addon, function(a) {
if (a) {
name.textContent = a.name;
}
});
time.textContent = addons[addon].time +"μs";
cpow.textContent = addons[addon].CPOWTime +"μs";
el.appendChild(time);
el.appendChild(cpow);
el.appendChild(name);
let div = document.createElement("tr");
for (let comp of addons[addon].compartments) {
let c = document.createElement("tr");
let name = document.createElement("td");
let time = document.createElement("td");
let cpow = document.createElement("td");
name.className = "addon";
time.className = "time";
cpow.className = "cpow";
name.textContent = comp.label;
time.textContent = comp.time +"μs";
cpow.textContent = comp.CPOWTime +"μs";
c.appendChild(time);
c.appendChild(cpow);
c.appendChild(name);
div.appendChild(c);
div.className = "details";
}
el.addEventListener("click", function() { div.style.display = (div.style.display != "block" ? "block" : "none"); });
el.appendChild(div);
dataDiv.appendChild(el);
}
}

View File

@ -0,0 +1,43 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>about:compartments</title>
<script type="text/javascript;version=1.8" src="chrome://global/content/aboutCompartments.js"></script>
<style>
td.addon {
display: inline-block;
width: 400px;
}
td.time {
display: inline-block;
width: 100px;
}
td.cpow {
display: inline-block;
width: 100px;
}
.header {
font-weight: bold;
}
tr.details {
font-weight: lighter;
color: gray;
display: none;
}
</style>
</head>
<body onload="go()">
<table id="data">
<tr class="header">
<td class="time">time</td>
<td class="cpow">time in CPOWs</td>
<td class="addon">name</td>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,7 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
toolkit.jar:
+ content/global/aboutCompartments.xhtml (content/aboutCompartments.xhtml)
+ content/global/aboutCompartments.js (content/aboutCompartments.js)

View File

@ -0,0 +1,23 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
JAR_MANIFESTS += ['jar.mn']
XPIDL_MODULE = 'compartments'
XPIDL_SOURCES += [
'nsICompartmentInfo.idl',
]
UNIFIED_SOURCES += [
'nsCompartmentInfo.cpp'
]
EXPORTS += [
'nsCompartmentInfo.h'
]
FINAL_LIBRARY = 'xul'

View File

@ -0,0 +1,94 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsCompartmentInfo.h"
#include "nsMemory.h"
#include "nsLiteralString.h"
#include "nsCRTGlue.h"
#include "nsIJSRuntimeService.h"
#include "nsServiceManagerUtils.h"
#include "nsIMutableArray.h"
#include "nsJSUtils.h"
#include "xpcpublic.h"
class nsCompartment : public nsICompartment {
public:
nsCompartment(nsAString& aCompartmentName, nsAString& aAddonId,
uint64_t aTime, uint64_t aCPOWTime)
: mCompartmentName(aCompartmentName), mAddonId(aAddonId), mTime(aTime), mCPOWTime(aCPOWTime) {}
NS_DECL_ISUPPORTS
/* readonly attribute wstring compartmentName; */
NS_IMETHOD GetCompartmentName(nsAString& aCompartmentName){
aCompartmentName.Assign(mCompartmentName);
return NS_OK;
};
/* readonly attribute unsigned long time; */
NS_IMETHOD GetTime(uint64_t* aTime) {
*aTime = mTime;
return NS_OK;
}
/* readonly attribute wstring addon id; */
NS_IMETHOD GetAddonId(nsAString& aAddonId){
aAddonId.Assign(mAddonId);
return NS_OK;
};
/* readonly attribute unsigned long CPOW time; */
NS_IMETHOD GetCPOWTime(uint64_t* aCPOWTime) {
*aCPOWTime = mCPOWTime;
return NS_OK;
}
private:
nsString mCompartmentName;
nsString mAddonId;
uint64_t mTime;
uint64_t mCPOWTime;
virtual ~nsCompartment() {}
};
NS_IMPL_ISUPPORTS(nsCompartment, nsICompartment)
NS_IMPL_ISUPPORTS(nsCompartmentInfo, nsICompartmentInfo)
nsCompartmentInfo::nsCompartmentInfo()
{
}
nsCompartmentInfo::~nsCompartmentInfo()
{
}
NS_IMETHODIMP
nsCompartmentInfo::GetCompartments(nsIArray** aCompartments)
{
JSRuntime* rt;
nsCOMPtr<nsIJSRuntimeService> svc(do_GetService("@mozilla.org/js/xpc/RuntimeService;1"));
NS_ENSURE_TRUE(svc, NS_ERROR_FAILURE);
svc->GetRuntime(&rt);
nsCOMPtr<nsIMutableArray> compartments = do_CreateInstance(NS_ARRAY_CONTRACTID);
CompartmentStatsVector stats;
if (!JS_GetCompartmentStats(rt, stats))
return NS_ERROR_OUT_OF_MEMORY;
size_t num = stats.length();
for (size_t pos = 0; pos < num; pos++) {
nsString addonId;
if (stats[pos].addonId) {
AssignJSFlatString(addonId, (JSFlatString*)stats[pos].addonId);
} else {
addonId.AssignLiteral("<non-addon>");
}
uint32_t cpowTime = xpc::GetCompartmentCPOWMicroseconds(stats[pos].compartment);
nsCString compartmentName(stats[pos].compartmentName);
NS_ConvertUTF8toUTF16 name(compartmentName);
compartments->AppendElement(new nsCompartment(name, addonId, stats[pos].time, cpowTime), false);
}
compartments.forget(aCompartments);
return NS_OK;
}

View File

@ -0,0 +1,25 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsCompartmentInfo_h
#define nsCompartmentInfo_h
#include "nsICompartmentInfo.h"
class nsCompartmentInfo : public nsICompartmentInfo
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICOMPARTMENTINFO
nsCompartmentInfo();
private:
virtual ~nsCompartmentInfo();
protected:
};
#endif

View File

@ -0,0 +1,31 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-*/
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
#include "nsIArray.idl"
[scriptable, uuid(13dd4c09-ff11-4943-8dc2-d96eb69c963b)]
interface nsICompartment : nsISupports {
/* name of compartment */
readonly attribute AString compartmentName;
/* time spent executing code in this compartment in microseconds */
readonly attribute unsigned long long time;
/* the id of the addon associated with this compartment, or null */
readonly attribute AString addonId;
/* time spent processing CPOWs in microseconds */
readonly attribute unsigned long long CPOWTime;
};
[scriptable, builtinclass, uuid(5795113a-39a1-4087-ba09-98b7d07d025a)]
interface nsICompartmentInfo : nsISupports {
nsIArray getCompartments();
};
%{C++
#define NS_COMPARTMENT_INFO_CID \
{ 0x2d3c2f2d, 0x698d, 0x471d, \
{ 0xba, 0x3e, 0x14, 0x44, 0xdd, 0x52, 0x1e, 0x29 } }
%}

View File

@ -3,7 +3,6 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
toolkit.jar:
+ content/global/aboutCompartments.xhtml (content/aboutCompartments.xhtml)
+ content/global/aboutMemory.js (content/aboutMemory.js)
+ content/global/aboutMemory.xhtml (content/aboutMemory.xhtml)
+ content/global/aboutMemory.css (content/aboutMemory.css)

View File

@ -10,6 +10,7 @@ if CONFIG['MOZ_ENABLE_XREMOTE']:
DIRS += [
'aboutcache',
'aboutcompartments',
'aboutmemory',
'addoncompat',
'alerts',

View File

@ -50,6 +50,8 @@
#include "nsThreadManager.h"
#include "nsThreadPool.h"
#include "nsCompartmentInfo.h"
#include "xptinfo.h"
#include "nsIInterfaceInfoManager.h"
#include "xptiprivate.h"
@ -234,6 +236,8 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsMemoryInfoDumper)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStatusReporterManager, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsCompartmentInfo)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsIOUtil)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSecurityConsoleMessage)

View File

@ -82,3 +82,4 @@
COMPONENT(CYCLE_COLLECTOR_LOGGER, nsCycleCollectorLoggerConstructor)
COMPONENT(MESSAGE_LOOP, nsMessageLoopConstructor)
COMPONENT(STATUS_REPORTER_MANAGER, nsStatusReporterManagerConstructor)
COMPONENT(COMPARTMENT_INFO, nsCompartmentInfoConstructor)

View File

@ -90,6 +90,8 @@
*/
#define NS_MESSAGE_LOOP_CONTRACTID "@mozilla.org/message-loop;1"
#define NS_COMPARTMENT_INFO_CONTRACTID "@mozilla.org/compartment-info;1"
/**
* The following are the CIDs and Contract IDs of the nsISupports wrappers for
* primative types.