зеркало из 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;
|
||||
bool autoclose = false;
|
||||
double delay = 0.0;
|
||||
bool captureProfile = false;
|
||||
nsString profileFilename;
|
||||
|
||||
rv =
|
||||
HandleFlagWithOptionalArgument(aCmdLine, NS_LITERAL_STRING("layoutdebug"),
|
||||
EmptyString(), url, flagPresent);
|
||||
rv = HandleFlagWithOptionalArgument(
|
||||
aCmdLine, NS_LITERAL_STRING("layoutdebug"),
|
||||
NS_LITERAL_STRING("about:blank"), url, flagPresent);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!flagPresent) {
|
||||
|
@ -113,21 +115,24 @@ nsLayoutDebugCLH::Handle(nsICommandLine* aCmdLine) {
|
|||
0.0, delay, autoclose);
|
||||
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();
|
||||
|
||||
if (!url.IsEmpty()) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsAutoCString resolvedSpec;
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsAutoCString resolvedSpec;
|
||||
|
||||
rv = aCmdLine->ResolveURI(url, getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aCmdLine->ResolveURI(url, getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = uri->GetSpec(resolvedSpec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = uri->GetSpec(resolvedSpec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = AppendArg(argsArray, NS_ConvertUTF8toUTF16(resolvedSpec));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
rv = AppendArg(argsArray, NS_ConvertUTF8toUTF16(resolvedSpec));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (autoclose) {
|
||||
nsString arg;
|
||||
|
@ -137,6 +142,15 @@ nsLayoutDebugCLH::Handle(nsICommandLine* aCmdLine) {
|
|||
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 =
|
||||
do_GetService(NS_WINDOWWATCHER_CONTRACTID);
|
||||
NS_ENSURE_TRUE(wwatch, NS_ERROR_FAILURE);
|
||||
|
@ -154,6 +168,10 @@ nsLayoutDebugCLH::GetHelpInfo(nsACString& aResult) {
|
|||
" --layoutdebug [<url>] Start with Layout Debugger\n"
|
||||
" --autoclose [<seconds>] Automatically close the Layout Debugger once\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;
|
||||
}
|
||||
|
|
|
@ -10,10 +10,13 @@ var gMultiProcessBrowser = window.docShell.QueryInterface(Ci.nsILoadContext)
|
|||
.useRemoteTabs;
|
||||
var gFissionBrowser = window.docShell.QueryInterface(Ci.nsILoadContext)
|
||||
.useRemoteSubframes;
|
||||
var gWritingProfile = false;
|
||||
var gWrittenProfile = false;
|
||||
|
||||
const { E10SUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/E10SUtils.jsm"
|
||||
);
|
||||
const { OS } = ChromeUtils.import("resource://gre/modules/osfile.jsm");
|
||||
const { Preferences } = ChromeUtils.import(
|
||||
"resource://gre/modules/Preferences.jsm"
|
||||
);
|
||||
|
@ -177,10 +180,13 @@ nsLDBBrowserContentListener.prototype = {
|
|||
// This does mean that --autoclose doesn't work when the URL on
|
||||
// the command line is about:blank (or not specified), but that's
|
||||
// not a big deal.
|
||||
setTimeout(
|
||||
() => Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit),
|
||||
gArgs.delay * 1000
|
||||
);
|
||||
setTimeout(function() {
|
||||
if (gArgs.profile && Services.profiler) {
|
||||
dumpProfile();
|
||||
} else {
|
||||
Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit);
|
||||
}
|
||||
}, gArgs.delay * 1000);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -234,11 +240,15 @@ function parseArguments() {
|
|||
if (window.arguments) {
|
||||
args.url = window.arguments[0];
|
||||
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.delay = +RegExp.$1;
|
||||
} else if (/^profile=(.*)$/.test(arg)) {
|
||||
args.profile = true;
|
||||
args.profileFilename = RegExp.$1;
|
||||
} else {
|
||||
throw `Unknown option ${window.arguments[i]}`;
|
||||
throw `Unknown option ${arg}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -262,6 +272,29 @@ function OnLDBLoad() {
|
|||
};
|
||||
|
||||
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) {
|
||||
loadURI(gArgs.url);
|
||||
}
|
||||
|
@ -283,6 +316,43 @@ function checkPersistentMenus() {
|
|||
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() {
|
||||
gDebugger.detachBrowser();
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
titlemenuseparator=" - "
|
||||
windowtype="mozapp:layoutdebug"
|
||||
onload="OnLDBLoad();"
|
||||
onclose="OnLDBBeforeUnload(event);"
|
||||
onunload="OnLDBUnload();"
|
||||
width="1024" height="768"
|
||||
screenX="4" screenY="4"
|
||||
|
|
Загрузка…
Ссылка в новой задаче