зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1569077 - Part 3: Add --capture-profile argument to the layout debugger. r=dbaron
Differential Revision: https://phabricator.services.mozilla.com/D39469 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
712f284101
Коммит
79a431d339
|
@ -99,10 +99,12 @@ nsLayoutDebugCLH::Handle(nsICommandLine* aCmdLine) {
|
||||||
nsString url;
|
nsString url;
|
||||||
bool autoclose = false;
|
bool autoclose = false;
|
||||||
double delay = 0.0;
|
double delay = 0.0;
|
||||||
|
bool captureProfile = false;
|
||||||
|
nsString profileFilename;
|
||||||
|
|
||||||
rv =
|
rv = HandleFlagWithOptionalArgument(
|
||||||
HandleFlagWithOptionalArgument(aCmdLine, NS_LITERAL_STRING("layoutdebug"),
|
aCmdLine, NS_LITERAL_STRING("layoutdebug"),
|
||||||
EmptyString(), url, flagPresent);
|
NS_LITERAL_STRING("about:blank"), url, flagPresent);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
if (!flagPresent) {
|
if (!flagPresent) {
|
||||||
|
@ -113,21 +115,24 @@ nsLayoutDebugCLH::Handle(nsICommandLine* aCmdLine) {
|
||||||
0.0, delay, autoclose);
|
0.0, delay, autoclose);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
rv = HandleFlagWithOptionalArgument(
|
||||||
|
aCmdLine, NS_LITERAL_STRING("capture-profile"),
|
||||||
|
NS_LITERAL_STRING("profile.json"), profileFilename, captureProfile);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
nsCOMPtr<nsIMutableArray> argsArray = nsArray::Create();
|
nsCOMPtr<nsIMutableArray> argsArray = nsArray::Create();
|
||||||
|
|
||||||
if (!url.IsEmpty()) {
|
nsCOMPtr<nsIURI> uri;
|
||||||
nsCOMPtr<nsIURI> uri;
|
nsAutoCString resolvedSpec;
|
||||||
nsAutoCString resolvedSpec;
|
|
||||||
|
|
||||||
rv = aCmdLine->ResolveURI(url, getter_AddRefs(uri));
|
rv = aCmdLine->ResolveURI(url, getter_AddRefs(uri));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
rv = uri->GetSpec(resolvedSpec);
|
rv = uri->GetSpec(resolvedSpec);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
rv = AppendArg(argsArray, NS_ConvertUTF8toUTF16(resolvedSpec));
|
rv = AppendArg(argsArray, NS_ConvertUTF8toUTF16(resolvedSpec));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
|
||||||
|
|
||||||
if (autoclose) {
|
if (autoclose) {
|
||||||
nsString arg;
|
nsString arg;
|
||||||
|
@ -137,6 +142,15 @@ nsLayoutDebugCLH::Handle(nsICommandLine* aCmdLine) {
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (captureProfile) {
|
||||||
|
nsString arg;
|
||||||
|
arg.AppendLiteral("profile=");
|
||||||
|
arg.Append(profileFilename);
|
||||||
|
|
||||||
|
rv = AppendArg(argsArray, arg);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIWindowWatcher> wwatch =
|
nsCOMPtr<nsIWindowWatcher> wwatch =
|
||||||
do_GetService(NS_WINDOWWATCHER_CONTRACTID);
|
do_GetService(NS_WINDOWWATCHER_CONTRACTID);
|
||||||
NS_ENSURE_TRUE(wwatch, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(wwatch, NS_ERROR_FAILURE);
|
||||||
|
@ -154,6 +168,10 @@ nsLayoutDebugCLH::GetHelpInfo(nsACString& aResult) {
|
||||||
" --layoutdebug [<url>] Start with Layout Debugger\n"
|
" --layoutdebug [<url>] Start with Layout Debugger\n"
|
||||||
" --autoclose [<seconds>] Automatically close the Layout Debugger once\n"
|
" --autoclose [<seconds>] Automatically close the Layout Debugger once\n"
|
||||||
" the page has loaded, after delaying the specified\n"
|
" the page has loaded, after delaying the specified\n"
|
||||||
" number of seconds (which defaults to 0).\n");
|
" number of seconds (which defaults to 0).\n"
|
||||||
|
" --capture-profile [<filename>] Capture a profile of the Layout\n"
|
||||||
|
" Debugger using the Gecko Profiler, and save the\n"
|
||||||
|
" profile to the specified file (which defaults to\n"
|
||||||
|
" profile.json).\n");
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,13 @@ var gMultiProcessBrowser = window.docShell.QueryInterface(Ci.nsILoadContext)
|
||||||
.useRemoteTabs;
|
.useRemoteTabs;
|
||||||
var gFissionBrowser = window.docShell.QueryInterface(Ci.nsILoadContext)
|
var gFissionBrowser = window.docShell.QueryInterface(Ci.nsILoadContext)
|
||||||
.useRemoteSubframes;
|
.useRemoteSubframes;
|
||||||
|
var gWritingProfile = false;
|
||||||
|
var gWrittenProfile = false;
|
||||||
|
|
||||||
const { E10SUtils } = ChromeUtils.import(
|
const { E10SUtils } = ChromeUtils.import(
|
||||||
"resource://gre/modules/E10SUtils.jsm"
|
"resource://gre/modules/E10SUtils.jsm"
|
||||||
);
|
);
|
||||||
|
const { OS } = ChromeUtils.import("resource://gre/modules/osfile.jsm");
|
||||||
const { Preferences } = ChromeUtils.import(
|
const { Preferences } = ChromeUtils.import(
|
||||||
"resource://gre/modules/Preferences.jsm"
|
"resource://gre/modules/Preferences.jsm"
|
||||||
);
|
);
|
||||||
|
@ -177,10 +180,13 @@ nsLDBBrowserContentListener.prototype = {
|
||||||
// This does mean that --autoclose doesn't work when the URL on
|
// This does mean that --autoclose doesn't work when the URL on
|
||||||
// the command line is about:blank (or not specified), but that's
|
// the command line is about:blank (or not specified), but that's
|
||||||
// not a big deal.
|
// not a big deal.
|
||||||
setTimeout(
|
setTimeout(function() {
|
||||||
() => Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit),
|
if (gArgs.profile && Services.profiler) {
|
||||||
gArgs.delay * 1000
|
dumpProfile();
|
||||||
);
|
} else {
|
||||||
|
Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit);
|
||||||
|
}
|
||||||
|
}, gArgs.delay * 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -234,11 +240,15 @@ function parseArguments() {
|
||||||
if (window.arguments) {
|
if (window.arguments) {
|
||||||
args.url = window.arguments[0];
|
args.url = window.arguments[0];
|
||||||
for (let i = 1; i < window.arguments.length; ++i) {
|
for (let i = 1; i < window.arguments.length; ++i) {
|
||||||
if (/^autoclose=(.*)$/.test(window.arguments[i])) {
|
let arg = window.arguments[i];
|
||||||
|
if (/^autoclose=(.*)$/.test(arg)) {
|
||||||
args.autoclose = true;
|
args.autoclose = true;
|
||||||
args.delay = +RegExp.$1;
|
args.delay = +RegExp.$1;
|
||||||
|
} else if (/^profile=(.*)$/.test(arg)) {
|
||||||
|
args.profile = true;
|
||||||
|
args.profileFilename = RegExp.$1;
|
||||||
} else {
|
} else {
|
||||||
throw `Unknown option ${window.arguments[i]}`;
|
throw `Unknown option ${arg}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,6 +272,29 @@ function OnLDBLoad() {
|
||||||
};
|
};
|
||||||
|
|
||||||
gArgs = parseArguments();
|
gArgs = parseArguments();
|
||||||
|
|
||||||
|
if (gArgs.profile) {
|
||||||
|
if (Services.profiler) {
|
||||||
|
let env = Cc["@mozilla.org/process/environment;1"].getService(
|
||||||
|
Ci.nsIEnvironment
|
||||||
|
);
|
||||||
|
if (!env.exists("MOZ_PROFILER_SYMBOLICATE")) {
|
||||||
|
dump(
|
||||||
|
"Warning: MOZ_PROFILER_SYMBOLICATE environment variable not set; " +
|
||||||
|
"profile will not be symbolicated.\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Services.profiler.StartProfiler(
|
||||||
|
1 << 20,
|
||||||
|
1,
|
||||||
|
["default"],
|
||||||
|
["GeckoMain", "Compositor", "Renderer", "RenderBackend", "StyleThread"]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
dump("Cannot profile Layout Debugger; profiler was not compiled in.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (gArgs.url) {
|
if (gArgs.url) {
|
||||||
loadURI(gArgs.url);
|
loadURI(gArgs.url);
|
||||||
}
|
}
|
||||||
|
@ -283,6 +316,43 @@ function checkPersistentMenus() {
|
||||||
checkPersistentMenu("reflowCounts");
|
checkPersistentMenu("reflowCounts");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function dumpProfile() {
|
||||||
|
gWritingProfile = true;
|
||||||
|
|
||||||
|
let cwd = Services.dirsvc.get("CurWorkD", Ci.nsIFile).path;
|
||||||
|
let filename = OS.Path.join(cwd, gArgs.profileFilename);
|
||||||
|
|
||||||
|
dump(`Writing profile to ${filename}...\n`);
|
||||||
|
|
||||||
|
Services.profiler.dumpProfileToFileAsync(filename).then(function() {
|
||||||
|
gWritingProfile = false;
|
||||||
|
gWrittenProfile = true;
|
||||||
|
dump(`done\n`);
|
||||||
|
Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function OnLDBBeforeUnload(event) {
|
||||||
|
if (gArgs.profile && Services.profiler) {
|
||||||
|
if (gWrittenProfile) {
|
||||||
|
// We've finished writing the profile. Allow the window to close.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
if (gWritingProfile) {
|
||||||
|
// Wait for the profile to finish being written out.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The dumpProfileToFileAsync call can block for a while, so run it off a
|
||||||
|
// timeout to avoid annoying the window manager if we're doing this in
|
||||||
|
// response to clicking the window's close button.
|
||||||
|
setTimeout(dumpProfile, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function OnLDBUnload() {
|
function OnLDBUnload() {
|
||||||
gDebugger.detachBrowser();
|
gDebugger.detachBrowser();
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
titlemenuseparator=" - "
|
titlemenuseparator=" - "
|
||||||
windowtype="mozapp:layoutdebug"
|
windowtype="mozapp:layoutdebug"
|
||||||
onload="OnLDBLoad();"
|
onload="OnLDBLoad();"
|
||||||
|
onclose="OnLDBBeforeUnload(event);"
|
||||||
onunload="OnLDBUnload();"
|
onunload="OnLDBUnload();"
|
||||||
width="1024" height="768"
|
width="1024" height="768"
|
||||||
screenX="4" screenY="4"
|
screenX="4" screenY="4"
|
||||||
|
|
Загрузка…
Ссылка в новой задаче