зеркало из https://github.com/mozilla/stoneridge.git
Import pageloader from talos
This commit is contained in:
Родитель
066250236c
Коммит
355446c352
|
@ -0,0 +1,65 @@
|
|||
Pageload Test Component
|
||||
=======================
|
||||
|
||||
Usage:
|
||||
|
||||
./firefox -tp file:///path/to/manifest.txt [-tpargs...]
|
||||
|
||||
See ./firefox -help for other arguments.
|
||||
|
||||
|
||||
Manifest file format
|
||||
====================
|
||||
|
||||
Comments in the manifest file start with a #. Each line may be:
|
||||
|
||||
* a URL (absolute or relative to the manifest)
|
||||
|
||||
This URL is added to the list of tests.
|
||||
|
||||
* one or more flags, followed by whitespace, followed by a URL
|
||||
|
||||
The only flag supported currently is '%', which indicates that
|
||||
a test will do its own timing. (See Self-timing Tests below.)
|
||||
|
||||
* "include" followed by whitespace, followed by a URL
|
||||
|
||||
Parse the given manifest file.
|
||||
|
||||
Self-timing Tests
|
||||
=================
|
||||
|
||||
Most timing tests are interested in timing how long it takes the page
|
||||
to load; that is, from the start of page loading until the 'load'
|
||||
event is dispatched. By default, this is what the pageloader will
|
||||
time. However, if a test URL has the % flag, the test is expected to
|
||||
report its own timing. For this purpose, the pageloader will provide
|
||||
a function named "tpRecordTime" in the test's global object that it
|
||||
should call once it has performed whatever timing it wants to do.
|
||||
The given value will be used as the timing result for this test.
|
||||
|
||||
Output format
|
||||
=============
|
||||
|
||||
The result is a dump to stdout via dump() --
|
||||
browser.dom.window.dump.enabled must be set to true in the profile.
|
||||
|
||||
Sample output:
|
||||
|
||||
__start_tp_report
|
||||
_x_x_mozilla_page_load,778.5,NaN,NaN
|
||||
_x_x_mozilla_page_load_details,avgmedian|778.5|average|766.75|minimum|NaN|maximum|NaN|stddev|NaN|0;file:///c:/proj/mozilla-cvs/perf/tp2/base/www.cnn.com/index.html;778.5;766.75;722;1027;1027;788;777;722;780|...
|
||||
__end_tp_report
|
||||
|
||||
Note that the minimum, maximum, stddev are not calculated; they're
|
||||
always reported as NaN. (They were the minimum and maximum values of
|
||||
any sampled value, and the standard deviation across all sampled
|
||||
values -- not very useful.)
|
||||
|
||||
TODO
|
||||
====
|
||||
|
||||
* Command line option to choose whether to run with or without browser chrome. Currently runs without.
|
||||
|
||||
* Tinderbox-dropping style output
|
||||
* better yet would be to teach tinderbox about JSON
|
|
@ -0,0 +1,4 @@
|
|||
content pageloader chrome/
|
||||
component {8AF052F5-8EFE-4359-8266-E16498A82E8B} components/tp-cmdline.js
|
||||
contract @mozilla.org/commandlinehandler/general-startup;1?type=tp {8AF052F5-8EFE-4359-8266-E16498A82E8B}
|
||||
category command-line-handler m-tp @mozilla.org/commandlinehandler/general-startup;1?type=tp
|
|
@ -0,0 +1,137 @@
|
|||
/**
|
||||
* MozillaFileLogger, a log listener that can write to a local file.
|
||||
*/
|
||||
|
||||
var ipcMode = false; // running in e10s build and need to use IPC?
|
||||
try {
|
||||
var ipcsanity = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch);
|
||||
ipcsanity.setIntPref("mochitest.ipcmode", 0);
|
||||
} catch (e) {
|
||||
ipcMode = true;
|
||||
}
|
||||
|
||||
function contentDispatchEvent(type, data, sync) {
|
||||
if (typeof(data) === "undefined") {
|
||||
data = {};
|
||||
}
|
||||
|
||||
var element = document.createEvent("datacontainerevent");
|
||||
element.initEvent("contentEvent", true, false);
|
||||
element.setData("sync", sync);
|
||||
element.setData("type", type);
|
||||
element.setData("data", JSON.stringify(data));
|
||||
document.dispatchEvent(element);
|
||||
}
|
||||
|
||||
function contentSyncEvent(type, data) {
|
||||
contentDispatchEvent(type, data, 1);
|
||||
}
|
||||
|
||||
function contentAsyncEvent(type, data) {
|
||||
contentDispatchEvent(type, data, 0);
|
||||
}
|
||||
|
||||
try {
|
||||
if (Cc === undefined) {
|
||||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
}
|
||||
} catch (ex) {} //running in ipcMode-chrome
|
||||
|
||||
try {
|
||||
const FOSTREAM_CID = "@mozilla.org/network/file-output-stream;1";
|
||||
const LF_CID = "@mozilla.org/file/local;1";
|
||||
|
||||
// File status flags. It is a bitwise OR of the following bit flags.
|
||||
// Only one of the first three flags below may be used.
|
||||
const PR_READ_ONLY = 0x01; // Open for reading only.
|
||||
const PR_WRITE_ONLY = 0x02; // Open for writing only.
|
||||
const PR_READ_WRITE = 0x04; // Open for reading and writing.
|
||||
|
||||
// If the file does not exist, the file is created.
|
||||
// If the file exists, this flag has no effect.
|
||||
const PR_CREATE_FILE = 0x08;
|
||||
|
||||
// The file pointer is set to the end of the file prior to each write.
|
||||
const PR_APPEND = 0x10;
|
||||
|
||||
// If the file exists, its length is truncated to 0.
|
||||
const PR_TRUNCATE = 0x20;
|
||||
|
||||
// If set, each write will wait for both the file data
|
||||
// and file status to be physically updated.
|
||||
const PR_SYNC = 0x40;
|
||||
|
||||
// If the file does not exist, the file is created. If the file already
|
||||
// exists, no action and NULL is returned.
|
||||
const PR_EXCL = 0x80;
|
||||
} catch (ex) {
|
||||
// probably not running in the test harness
|
||||
}
|
||||
|
||||
/** Init the file logger with the absolute path to the file.
|
||||
It will create and append if the file already exists **/
|
||||
var MozillaFileLogger = {};
|
||||
|
||||
|
||||
MozillaFileLogger.init = function(path) {
|
||||
if (ipcMode) {
|
||||
contentAsyncEvent("LoggerInit", {"filename": path});
|
||||
return;
|
||||
}
|
||||
|
||||
MozillaFileLogger._file = Cc[LF_CID].createInstance(Ci.nsILocalFile);
|
||||
MozillaFileLogger._file.initWithPath(path);
|
||||
MozillaFileLogger._foStream = Cc[FOSTREAM_CID].createInstance(Ci.nsIFileOutputStream);
|
||||
MozillaFileLogger._foStream.init(this._file, PR_WRITE_ONLY | PR_CREATE_FILE | PR_APPEND,
|
||||
0664, 0);
|
||||
}
|
||||
|
||||
MozillaFileLogger.getLogCallback = function() {
|
||||
if (ipcMode) {
|
||||
return function(msg) {
|
||||
contentAsyncEvent("Logger", {"num": msg.num, "level": msg.level, "info": msg.info.join(' ')});
|
||||
}
|
||||
}
|
||||
|
||||
return function (msg) {
|
||||
var data = msg.num + " " + msg.level + " " + msg.info.join(' ') + "\n";
|
||||
if (MozillaFileLogger._foStream)
|
||||
MozillaFileLogger._foStream.write(data, data.length);
|
||||
|
||||
if (data.indexOf("SimpleTest FINISH") >= 0) {
|
||||
MozillaFileLogger.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is only used from chrome space by the reftest harness
|
||||
MozillaFileLogger.log = function(msg) {
|
||||
if (MozillaFileLogger._foStream)
|
||||
MozillaFileLogger._foStream.write(msg, msg.length);
|
||||
}
|
||||
|
||||
MozillaFileLogger.close = function() {
|
||||
if (ipcMode) {
|
||||
contentAsyncEvent("LoggerClose");
|
||||
return;
|
||||
}
|
||||
|
||||
if(MozillaFileLogger._foStream)
|
||||
MozillaFileLogger._foStream.close();
|
||||
|
||||
MozillaFileLogger._foStream = null;
|
||||
MozillaFileLogger._file = null;
|
||||
}
|
||||
|
||||
if (ipcMode == false) {
|
||||
try {
|
||||
var prefs = Components.classes['@mozilla.org/preferences-service;1']
|
||||
.getService(Components.interfaces.nsIPrefBranch2);
|
||||
var filename = prefs.getCharPref('talos.logfile');
|
||||
MozillaFileLogger.init(filename);
|
||||
} catch (ex) {} //pref does not exist, return empty string
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
|
||||
var gChildProcess = true;
|
||||
var gMemCallback = null;
|
||||
|
||||
|
||||
/*
|
||||
* Initialize memory collector. Determine if we have a child process.
|
||||
*/
|
||||
function initializeMemoryCollector(callback, args) {
|
||||
gMemCallback = function() { return callback(args); };
|
||||
|
||||
var os = Components.classes["@mozilla.org/observer-service;1"].
|
||||
getService(Components.interfaces.nsIObserverService);
|
||||
|
||||
os.addObserver(function () {
|
||||
var os = Components.classes["@mozilla.org/observer-service;1"].
|
||||
getService(Components.interfaces.nsIObserverService);
|
||||
|
||||
memTimer.cancel();
|
||||
memTimer = null;
|
||||
|
||||
os.removeObserver(arguments.callee, "child-memory-reporter-update", false);
|
||||
os.addObserver(collectAndReport, "child-memory-reporter-update", false);
|
||||
gMemCallback();
|
||||
}, "child-memory-reporter-update", false);
|
||||
|
||||
/*
|
||||
* Assume we have a child process, but if timer fires before we call the observer
|
||||
* we will assume there is no child process.
|
||||
*/
|
||||
var event = {
|
||||
notify: function(timer) {
|
||||
memTimer = null;
|
||||
gChildProcess = false;
|
||||
gMemCallback();
|
||||
}
|
||||
}
|
||||
|
||||
memTimer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer);
|
||||
memTimer.initWithCallback(event, 10000, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
|
||||
|
||||
os.notifyObservers(null, "child-memory-reporter-request", null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Collect memory from all processes and callback when done collecting.
|
||||
*/
|
||||
function collectMemory(callback, args) {
|
||||
gMemCallback = function() { return callback(args); };
|
||||
|
||||
if (gChildProcess) {
|
||||
var os = Components.classes["@mozilla.org/observer-service;1"].
|
||||
getService(Components.interfaces.nsIObserverService);
|
||||
|
||||
os.notifyObservers(null, "child-memory-reporter-request", null);
|
||||
} else {
|
||||
collectAndReport(null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
function collectAndReport(aSubject, aTopic, aData) {
|
||||
dumpLine(collectRSS());
|
||||
gMemCallback();
|
||||
}
|
||||
|
||||
function collectRSS() {
|
||||
var mgr = Components.classes["@mozilla.org/memory-reporter-manager;1"].
|
||||
getService(Components.interfaces.nsIMemoryReporterManager);
|
||||
var e = mgr.enumerateReporters();
|
||||
text = "";
|
||||
while (e.hasMoreElements()) {
|
||||
var reporter = e.getNext().QueryInterface(Components.interfaces.nsIMemoryReporter);
|
||||
if (reporter.path == 'resident') {
|
||||
procName = reporter.process;
|
||||
if (procName == '')
|
||||
procName = "Main";
|
||||
|
||||
//For content process it is in the format "Content (<PID>)", we just want Content
|
||||
procName = procName.split(' ')[0];
|
||||
text += "RSS: " + procName + ": " + reporter.amount + "\n";
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cleanup and stop memory collector.
|
||||
*/
|
||||
function stopMemCollector() {
|
||||
if (gChildProcess) {
|
||||
var os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
os.removeObserver(collectAndReport, "child-memory-reporter-update");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,696 @@
|
|||
/* -*- Mode: C++; tab-width: 20; 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/. */
|
||||
|
||||
try {
|
||||
if (Cc === undefined) {
|
||||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
}
|
||||
} catch (ex) {}
|
||||
|
||||
var NUM_CYCLES = 5;
|
||||
var numPageCycles = 1;
|
||||
|
||||
var pageFilterRegexp = null;
|
||||
var useBrowser = true;
|
||||
var winWidth = 1024;
|
||||
var winHeight = 768;
|
||||
|
||||
var doRenderTest = false;
|
||||
|
||||
var pages;
|
||||
var pageIndex;
|
||||
var start_time;
|
||||
var cycle;
|
||||
var pageCycle;
|
||||
var report;
|
||||
var noisy = false;
|
||||
var timeout = -1;
|
||||
var delay = 250;
|
||||
var timeoutEvent = -1;
|
||||
var running = false;
|
||||
var forceCC = true;
|
||||
var reportRSS = true;
|
||||
|
||||
var useMozAfterPaint = false;
|
||||
var gPaintWindow = window;
|
||||
var gPaintListener = false;
|
||||
|
||||
//when TEST_DOES_OWN_TIMING, we need to store the time from the page as MozAfterPaint can be slower than pageload
|
||||
var gTime = -1;
|
||||
var gStartTime = -1;
|
||||
var gReference = -1;
|
||||
|
||||
var content;
|
||||
|
||||
var TEST_DOES_OWN_TIMING = 1;
|
||||
|
||||
var browserWindow = null;
|
||||
|
||||
var recordedName = null;
|
||||
var pageUrls;
|
||||
|
||||
// the io service
|
||||
var gIOS = null;
|
||||
|
||||
function plInit() {
|
||||
if (running) {
|
||||
return;
|
||||
}
|
||||
running = true;
|
||||
|
||||
cycle = 0;
|
||||
pageCycle = 1;
|
||||
|
||||
try {
|
||||
var args = window.arguments[0].wrappedJSObject;
|
||||
|
||||
var manifestURI = args.manifest;
|
||||
var startIndex = 0;
|
||||
var endIndex = -1;
|
||||
if (args.startIndex) startIndex = parseInt(args.startIndex);
|
||||
if (args.endIndex) endIndex = parseInt(args.endIndex);
|
||||
if (args.numCycles) NUM_CYCLES = parseInt(args.numCycles);
|
||||
if (args.numPageCycles) numPageCycles = parseInt(args.numPageCycles);
|
||||
if (args.width) winWidth = parseInt(args.width);
|
||||
if (args.height) winHeight = parseInt(args.height);
|
||||
if (args.filter) pageFilterRegexp = new RegExp(args.filter);
|
||||
if (args.noisy) noisy = true;
|
||||
if (args.timeout) timeout = parseInt(args.timeout);
|
||||
if (args.delay) delay = parseInt(args.delay);
|
||||
if (args.mozafterpaint) useMozAfterPaint = true;
|
||||
if (args.rss) reportRSS = true;
|
||||
|
||||
forceCC = !args.noForceCC;
|
||||
doRenderTest = args.doRender;
|
||||
|
||||
if (forceCC &&
|
||||
!window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils)
|
||||
.garbageCollect) {
|
||||
forceCC = false;
|
||||
}
|
||||
|
||||
gIOS = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Ci.nsIIOService);
|
||||
if (args.offline)
|
||||
gIOS.offline = true;
|
||||
var fileURI = gIOS.newURI(manifestURI, null, null);
|
||||
pages = plLoadURLsFromURI(fileURI);
|
||||
|
||||
if (!pages) {
|
||||
dumpLine('tp: could not load URLs, quitting');
|
||||
plStop(true);
|
||||
}
|
||||
|
||||
if (pages.length == 0) {
|
||||
dumpLine('tp: no pages to test, quitting');
|
||||
plStop(true);
|
||||
}
|
||||
|
||||
if (startIndex < 0)
|
||||
startIndex = 0;
|
||||
if (endIndex == -1 || endIndex >= pages.length)
|
||||
endIndex = pages.length-1;
|
||||
if (startIndex > endIndex) {
|
||||
dumpLine("tp: error: startIndex >= endIndex");
|
||||
plStop(true);
|
||||
}
|
||||
|
||||
pages = pages.slice(startIndex,endIndex+1);
|
||||
pageUrls = pages.map(function(p) { return p.url.spec.toString(); });
|
||||
report = new Report();
|
||||
|
||||
if (doRenderTest)
|
||||
renderReport = new Report();
|
||||
|
||||
pageIndex = 0;
|
||||
|
||||
if (args.useBrowserChrome) {
|
||||
var wwatch = Cc["@mozilla.org/embedcomp/window-watcher;1"]
|
||||
.getService(Ci.nsIWindowWatcher);
|
||||
var blank = Cc["@mozilla.org/supports-string;1"]
|
||||
.createInstance(Ci.nsISupportsString);
|
||||
blank.data = "about:blank";
|
||||
browserWindow = wwatch.openWindow
|
||||
(null, "chrome://browser/content/", "_blank",
|
||||
"chrome,all,dialog=no,width=" + winWidth + ",height=" + winHeight, blank);
|
||||
|
||||
gPaintWindow = browserWindow;
|
||||
// get our window out of the way
|
||||
window.resizeTo(10,10);
|
||||
|
||||
var browserLoadFunc = function (ev) {
|
||||
browserWindow.removeEventListener('load', browserLoadFunc, true);
|
||||
|
||||
// do this half a second after load, because we need to be
|
||||
// able to resize the window and not have it get clobbered
|
||||
// by the persisted values
|
||||
setTimeout(function () {
|
||||
browserWindow.resizeTo(winWidth, winHeight);
|
||||
browserWindow.moveTo(0, 0);
|
||||
browserWindow.focus();
|
||||
|
||||
content = browserWindow.getBrowser();
|
||||
|
||||
// Load the frame script for e10s / IPC message support
|
||||
if (content.getAttribute("remote") == "true") {
|
||||
let contentScript = "data:,function _contentLoadHandler(e) { " +
|
||||
" if (e.originalTarget.defaultView == content) { " +
|
||||
" content.wrappedJSObject.tpRecordTime = function(t, s) { sendAsyncMessage('PageLoader:RecordTime', { time: t, startTime: s }); }; ";
|
||||
if (useMozAfterPaint) {
|
||||
contentScript += "" +
|
||||
"function _contentPaintHandler() { " +
|
||||
" var utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindowUtils); " +
|
||||
" if (utils.isMozAfterPaintPending) { " +
|
||||
" addEventListener('MozAfterPaint', function(e) { " +
|
||||
" removeEventListener('MozAfterPaint', arguments.callee, true); " +
|
||||
" sendAsyncMessage('PageLoader:MozAfterPaint', {}); " +
|
||||
" }, true); " +
|
||||
" } else { " +
|
||||
" sendAsyncMessage('PageLoader:MozAfterPaint', {}); " +
|
||||
" } " +
|
||||
"}; " +
|
||||
"content.wrappedJSObject.setTimeout(_contentPaintHandler, 0); ";
|
||||
} else {
|
||||
contentScript += " sendAsyncMessage('PageLoader:Load', {}); ";
|
||||
}
|
||||
contentScript += "" +
|
||||
" }" +
|
||||
"} " +
|
||||
"addEventListener('load', _contentLoadHandler, true); ";
|
||||
content.messageManager.loadFrameScript(contentScript, false);
|
||||
}
|
||||
if (reportRSS) {
|
||||
initializeMemoryCollector(plLoadPage, 100);
|
||||
} else {
|
||||
setTimeout(plLoadPage, 100);
|
||||
}
|
||||
}, 500);
|
||||
};
|
||||
|
||||
browserWindow.addEventListener('load', browserLoadFunc, true);
|
||||
} else {
|
||||
gPaintWindow = window;
|
||||
window.resizeTo(winWidth, winHeight);
|
||||
|
||||
content = document.getElementById('contentPageloader');
|
||||
|
||||
if (reportRSS) {
|
||||
initializeMemoryCollector(plLoadPage, delay);
|
||||
} else {
|
||||
setTimeout(plLoadPage, delay);
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
dumpLine(e);
|
||||
plStop(true);
|
||||
}
|
||||
}
|
||||
|
||||
function plPageFlags() {
|
||||
return pages[pageIndex].flags;
|
||||
}
|
||||
|
||||
// load the current page, start timing
|
||||
var removeLastAddedListener = null;
|
||||
var removeLastAddedMsgListener = null;
|
||||
function plLoadPage() {
|
||||
var pageName = pages[pageIndex].url.spec;
|
||||
|
||||
if (removeLastAddedListener)
|
||||
removeLastAddedListener();
|
||||
|
||||
if (removeLastAddedMsgListener)
|
||||
removeLastAddedMsgListener();
|
||||
|
||||
if (plPageFlags() & TEST_DOES_OWN_TIMING) {
|
||||
// if the page does its own timing, use a capturing handler
|
||||
// to make sure that we can set up the function for content to call
|
||||
|
||||
content.addEventListener('load', plLoadHandlerCapturing, true);
|
||||
removeLastAddedListener = function() {
|
||||
content.removeEventListener('load', plLoadHandlerCapturing, true);
|
||||
if (useMozAfterPaint) {
|
||||
content.removeEventListener("MozAfterPaint", plPaintedCapturing, true);
|
||||
gPaintListener = false;
|
||||
}
|
||||
};
|
||||
} else {
|
||||
// if the page doesn't do its own timing, use a bubbling handler
|
||||
// to make sure that we're called after the page's own onload() handling
|
||||
|
||||
// XXX we use a capturing event here too -- load events don't bubble up
|
||||
// to the <browser> element. See bug 390263.
|
||||
content.addEventListener('load', plLoadHandler, true);
|
||||
removeLastAddedListener = function() {
|
||||
content.removeEventListener('load', plLoadHandler, true);
|
||||
if (useMozAfterPaint) {
|
||||
gPaintWindow.removeEventListener("MozAfterPaint", plPainted, true);
|
||||
gPaintListener = false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// If the test browser is remote (e10s / IPC) we need to use messages to watch for page load
|
||||
if (content.getAttribute("remote") == "true") {
|
||||
content.messageManager.addMessageListener('PageLoader:Load', plLoadHandlerMessage);
|
||||
content.messageManager.addMessageListener('PageLoader:RecordTime', plRecordTimeMessage);
|
||||
if (useMozAfterPaint)
|
||||
content.messageManager.addMessageListener('PageLoader:MozAfterPaint', plPaintHandler);
|
||||
removeLastAddedMsgListener = function() {
|
||||
content.messageManager.removeMessageListener('PageLoader:Load', plLoadHandlerMessage);
|
||||
content.messageManager.removeMessageListener('PageLoader:RecordTime', plRecordTimeMessage);
|
||||
if (useMozAfterPaint)
|
||||
content.messageManager.removeMessageListener('PageLoader:MozAfterPaint', plPaintHandler);
|
||||
};
|
||||
}
|
||||
|
||||
if (timeout > 0) {
|
||||
timeoutEvent = setTimeout('loadFail()', timeout);
|
||||
}
|
||||
if (reportRSS) {
|
||||
collectMemory(startAndLoadURI, pageName);
|
||||
} else {
|
||||
startAndLoadURI(pageName);
|
||||
}
|
||||
}
|
||||
|
||||
function startAndLoadURI(pageName) {
|
||||
start_time = Date.now();
|
||||
content.loadURI(pageName);
|
||||
}
|
||||
|
||||
function loadFail() {
|
||||
var pageName = pages[pageIndex].url.spec;
|
||||
dumpLine("__FAILTimeout exceeded on " + pageName + "__FAIL")
|
||||
plStop(true);
|
||||
}
|
||||
|
||||
function plNextPage() {
|
||||
var doNextPage = false;
|
||||
if (pageCycle < numPageCycles) {
|
||||
pageCycle++;
|
||||
doNextPage = true;
|
||||
} else if (pageIndex < pages.length-1) {
|
||||
pageIndex++;
|
||||
recordedName = null;
|
||||
pageCycle = 1;
|
||||
doNextPage = true;
|
||||
}
|
||||
|
||||
if (doNextPage == true) {
|
||||
if (forceCC) {
|
||||
var tccstart = new Date();
|
||||
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils)
|
||||
.garbageCollect();
|
||||
var tccend = new Date();
|
||||
report.recordCCTime(tccend - tccstart);
|
||||
}
|
||||
|
||||
setTimeout(plLoadPage, delay);
|
||||
} else {
|
||||
plStop(false);
|
||||
}
|
||||
}
|
||||
|
||||
function plRecordTime(time) {
|
||||
var pageName = pages[pageIndex].url.spec;
|
||||
var i = pageIndex
|
||||
if (i < pages.length-1) {
|
||||
i++;
|
||||
} else {
|
||||
i = 0;
|
||||
}
|
||||
var nextName = pages[i].url.spec;
|
||||
if (!recordedName) {
|
||||
recordedName = pageUrls[pageIndex];
|
||||
}
|
||||
if (typeof(time) == "string") {
|
||||
var times = time.split(',');
|
||||
var names = recordedName.split(',');
|
||||
for (var t = 0; t < times.length; t++) {
|
||||
if (names.length == 1) {
|
||||
report.recordTime(names, times[t]);
|
||||
} else {
|
||||
report.recordTime(names[t], times[t]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
report.recordTime(recordedName, time);
|
||||
}
|
||||
if (noisy) {
|
||||
dumpLine("Cycle " + (cycle+1) + "(" + pageCycle + ")" + ": loaded " + pageName + " (next: " + nextName + ")");
|
||||
}
|
||||
}
|
||||
|
||||
function plLoadHandlerCapturing(evt) {
|
||||
// make sure we pick up the right load event
|
||||
if (evt.type != 'load' ||
|
||||
evt.originalTarget.defaultView.frameElement)
|
||||
return;
|
||||
|
||||
//set the tpRecordTime function (called from test pages we load to store a global time.
|
||||
content.contentWindow.wrappedJSObject.tpRecordTime = function (time, startTime, testName) {
|
||||
gTime = time;
|
||||
gStartTime = startTime;
|
||||
recordedName = testName;
|
||||
setTimeout(plWaitForPaintingCapturing, 0);
|
||||
}
|
||||
|
||||
content.removeEventListener('load', plLoadHandlerCapturing, true);
|
||||
|
||||
setTimeout(plWaitForPaintingCapturing, 0);
|
||||
}
|
||||
|
||||
function plWaitForPaintingCapturing() {
|
||||
if (gPaintListener)
|
||||
return;
|
||||
|
||||
var utils = gPaintWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
|
||||
if (utils.isMozAfterPaintPending && useMozAfterPaint) {
|
||||
if (gPaintListener == false)
|
||||
gPaintWindow.addEventListener("MozAfterPaint", plPaintedCapturing, true);
|
||||
gPaintListener = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_loadHandlerCapturing();
|
||||
}
|
||||
|
||||
function plPaintedCapturing() {
|
||||
gPaintWindow.removeEventListener("MozAfterPaint", plPaintedCapturing, true);
|
||||
gPaintListener = false;
|
||||
_loadHandlerCapturing();
|
||||
}
|
||||
|
||||
function _loadHandlerCapturing() {
|
||||
if (timeout > 0) {
|
||||
clearTimeout(timeoutEvent);
|
||||
}
|
||||
|
||||
if (!(plPageFlags() & TEST_DOES_OWN_TIMING)) {
|
||||
dumpLine("tp: Capturing onload handler used with page that doesn't do its own timing?");
|
||||
plStop(true);
|
||||
}
|
||||
|
||||
if (useMozAfterPaint) {
|
||||
if (gStartTime != null && gStartTime >= 0) {
|
||||
gTime = (new Date()) - gStartTime;
|
||||
gStartTime = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// set up the function for content to call
|
||||
if (gTime != -1) {
|
||||
plRecordTime(gTime);
|
||||
gTime = -1;
|
||||
recordedName = null;
|
||||
setTimeout(plNextPage, delay);
|
||||
};
|
||||
}
|
||||
|
||||
// the onload handler
|
||||
function plLoadHandler(evt) {
|
||||
// make sure we pick up the right load event
|
||||
if (evt.type != 'load' ||
|
||||
evt.originalTarget.defaultView.frameElement)
|
||||
return;
|
||||
|
||||
content.removeEventListener('load', plLoadHandler, true);
|
||||
setTimeout(waitForPainted, 0);
|
||||
}
|
||||
|
||||
// This is called after we have received a load event, now we wait for painted
|
||||
function waitForPainted() {
|
||||
|
||||
var utils = gPaintWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
|
||||
if (!utils.isMozAfterPaintPending || !useMozAfterPaint) {
|
||||
_loadHandler();
|
||||
return;
|
||||
}
|
||||
|
||||
if (gPaintListener == false)
|
||||
gPaintWindow.addEventListener("MozAfterPaint", plPainted, true);
|
||||
gPaintListener = true;
|
||||
}
|
||||
|
||||
function plPainted() {
|
||||
gPaintWindow.removeEventListener("MozAfterPaint", plPainted, true);
|
||||
gPaintListener = false;
|
||||
_loadHandler();
|
||||
}
|
||||
|
||||
function _loadHandler() {
|
||||
if (timeout > 0) {
|
||||
clearTimeout(timeoutEvent);
|
||||
}
|
||||
var docElem;
|
||||
if (browserWindow)
|
||||
docElem = browserWindow.frames["content"].document.documentElement;
|
||||
else
|
||||
docElem = content.contentDocument.documentElement;
|
||||
var width;
|
||||
if ("getBoundingClientRect" in docElem) {
|
||||
width = docElem.getBoundingClientRect().width;
|
||||
} else if ("offsetWidth" in docElem) {
|
||||
width = docElem.offsetWidth;
|
||||
}
|
||||
|
||||
var end_time = Date.now();
|
||||
var time = (end_time - start_time);
|
||||
|
||||
// does this page want to do its own timing?
|
||||
// if so, we shouldn't be here
|
||||
if (plPageFlags() & TEST_DOES_OWN_TIMING) {
|
||||
dumpLine("tp: Bubbling onload handler used with page that does its own timing?");
|
||||
plStop(true);
|
||||
}
|
||||
|
||||
plRecordTime(time);
|
||||
|
||||
if (doRenderTest)
|
||||
runRenderTest();
|
||||
|
||||
plNextPage();
|
||||
}
|
||||
|
||||
// the onload handler used for remote (e10s) browser
|
||||
function plLoadHandlerMessage(message) {
|
||||
_loadHandlerMessage();
|
||||
}
|
||||
|
||||
// the mozafterpaint handler for remote (e10s) browser
|
||||
function plPaintHandler(message) {
|
||||
_loadHandlerMessage();
|
||||
}
|
||||
|
||||
// the core handler for remote (e10s) browser
|
||||
function _loadHandlerMessage() {
|
||||
if (timeout > 0) {
|
||||
clearTimeout(timeoutEvent);
|
||||
}
|
||||
|
||||
var time = -1;
|
||||
|
||||
// does this page want to do its own timing?
|
||||
if ((plPageFlags() & TEST_DOES_OWN_TIMING)) {
|
||||
if (typeof(gStartTime) != "number")
|
||||
gStartTime = Date.parse(gStartTime);
|
||||
|
||||
if (gTime >= 0) {
|
||||
if (useMozAfterPaint && gStartTime >= 0) {
|
||||
gTime = Date.now() - gStartTime;
|
||||
gStartTime = -1;
|
||||
} else if (useMozAfterPaint) {
|
||||
gTime = -1;
|
||||
}
|
||||
time = gTime;
|
||||
gTime = -1;
|
||||
}
|
||||
|
||||
} else {
|
||||
var end_time = Date.now();
|
||||
time = (end_time - start_time);
|
||||
}
|
||||
|
||||
if (time >= 0) {
|
||||
plRecordTime(time);
|
||||
if (doRenderTest)
|
||||
runRenderTest();
|
||||
|
||||
plNextPage();
|
||||
}
|
||||
}
|
||||
|
||||
// the record time handler used for remote (e10s) browser
|
||||
function plRecordTimeMessage(message) {
|
||||
gTime = message.json.time;
|
||||
if (useMozAfterPaint) {
|
||||
gStartTime = message.json.startTime;
|
||||
}
|
||||
_loadHandlerMessage();
|
||||
}
|
||||
|
||||
function runRenderTest() {
|
||||
const redrawsPerSample = 500;
|
||||
|
||||
if (!Ci.nsIDOMWindowUtils)
|
||||
return;
|
||||
|
||||
var win;
|
||||
|
||||
if (browserWindow)
|
||||
win = content.contentWindow;
|
||||
else
|
||||
win = window;
|
||||
var wu = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
var start = Date.now();
|
||||
for (var j = 0; j < redrawsPerSample; j++)
|
||||
wu.redraw();
|
||||
var end = Date.now();
|
||||
|
||||
renderReport.recordTime(pageIndex, end - start);
|
||||
}
|
||||
|
||||
function plStop(force) {
|
||||
if (reportRSS) {
|
||||
collectMemory(plStopAll, force);
|
||||
} else {
|
||||
plStopAll(force);
|
||||
}
|
||||
}
|
||||
|
||||
function plStopAll(force) {
|
||||
try {
|
||||
if (force == false) {
|
||||
pageIndex = 0;
|
||||
pageCycle = 1;
|
||||
if (cycle < NUM_CYCLES-1) {
|
||||
cycle++;
|
||||
recordedName = null;
|
||||
setTimeout(plLoadPage, delay);
|
||||
return;
|
||||
}
|
||||
|
||||
/* output report */
|
||||
dumpLine(report.getReport());
|
||||
}
|
||||
} catch (e) {
|
||||
dumpLine(e);
|
||||
}
|
||||
|
||||
if (reportRSS) {
|
||||
stopMemCollector();
|
||||
}
|
||||
|
||||
if (content) {
|
||||
content.removeEventListener('load', plLoadHandlerCapturing, true);
|
||||
content.removeEventListener('load', plLoadHandler, true);
|
||||
if (useMozAfterPaint)
|
||||
content.removeEventListener("MozAfterPaint", plPaintedCapturing, true);
|
||||
content.removeEventListener("MozAfterPaint", plPainted, true);
|
||||
|
||||
if (content.getAttribute("remote") == "true") {
|
||||
content.messageManager.removeMessageListener('PageLoader:Load', plLoadHandlerMessage);
|
||||
content.messageManager.removeMessageListener('PageLoader:RecordTime', plRecordTimeMessage);
|
||||
if (useMozAfterPaint)
|
||||
content.messageManager.removeMessageListener('PageLoader:MozAfterPaint', plPaintHandler);
|
||||
|
||||
content.messageManager.loadFrameScript("data:,removeEventListener('load', _contentLoadHandler, true);", false);
|
||||
}
|
||||
}
|
||||
|
||||
if (MozillaFileLogger)
|
||||
MozillaFileLogger.close();
|
||||
|
||||
goQuitApplication();
|
||||
}
|
||||
|
||||
/* Returns array */
|
||||
function plLoadURLsFromURI(manifestUri) {
|
||||
var fstream = Cc["@mozilla.org/network/file-input-stream;1"]
|
||||
.createInstance(Ci.nsIFileInputStream);
|
||||
var uriFile = manifestUri.QueryInterface(Ci.nsIFileURL);
|
||||
|
||||
fstream.init(uriFile.file, -1, 0, 0);
|
||||
var lstream = fstream.QueryInterface(Ci.nsILineInputStream);
|
||||
|
||||
var d = [];
|
||||
|
||||
var lineNo = 0;
|
||||
var line = {value:null};
|
||||
var more;
|
||||
do {
|
||||
lineNo++;
|
||||
more = lstream.readLine(line);
|
||||
var s = line.value;
|
||||
|
||||
// strip comments
|
||||
s = s.replace(/#.*/, '');
|
||||
|
||||
// strip leading and trailing whitespace
|
||||
s = s.replace(/^\s*/, '').replace(/\s*$/, '');
|
||||
|
||||
if (!s)
|
||||
continue;
|
||||
|
||||
var flags = 0;
|
||||
var urlspec = s;
|
||||
|
||||
// split on whitespace, and figure out if we have any flags
|
||||
var items = s.split(/\s+/);
|
||||
if (items[0] == "include") {
|
||||
if (items.length != 2) {
|
||||
dumpLine("tp: Error on line " + lineNo + " in " + manifestUri.spec + ": include must be followed by the manifest to include!");
|
||||
return null;
|
||||
}
|
||||
|
||||
var subManifest = gIOS.newURI(items[1], null, manifestUri);
|
||||
if (subManifest == null) {
|
||||
dumpLine("tp: invalid URI on line " + manifestUri.spec + ":" + lineNo + " : '" + line.value + "'");
|
||||
return null;
|
||||
}
|
||||
|
||||
var subItems = plLoadURLsFromURI(subManifest);
|
||||
if (subItems == null)
|
||||
return null;
|
||||
d = d.concat(subItems);
|
||||
} else {
|
||||
if (items.length == 2) {
|
||||
if (items[0].indexOf("%") != -1)
|
||||
flags |= TEST_DOES_OWN_TIMING;
|
||||
|
||||
urlspec = items[1];
|
||||
} else if (items.length != 1) {
|
||||
dumpLine("tp: Error on line " + lineNo + " in " + manifestUri.spec + ": whitespace must be %-escaped!");
|
||||
return null;
|
||||
}
|
||||
|
||||
var url = gIOS.newURI(urlspec, null, manifestUri);
|
||||
|
||||
if (pageFilterRegexp && !pageFilterRegexp.test(url.spec))
|
||||
continue;
|
||||
|
||||
d.push({ url: url,
|
||||
flags: flags });
|
||||
}
|
||||
} while (more);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
function dumpLine(str) {
|
||||
if (MozillaFileLogger)
|
||||
MozillaFileLogger.log(str + "\n");
|
||||
dump(str);
|
||||
dump("\n");
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- ***** BEGIN LICENSE BLOCK *****
|
||||
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
-
|
||||
- The contents of this file are subject to the Mozilla Public License Version
|
||||
- 1.1 (the "License"); you may not use this file except in compliance with
|
||||
- the License. You may obtain a copy of the License at
|
||||
- http://www.mozilla.org/MPL/
|
||||
-
|
||||
- Software distributed under the License is distributed on an "AS IS" basis,
|
||||
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
- for the specific language governing rights and limitations under the
|
||||
- License.
|
||||
-
|
||||
- The Original Code is tp.
|
||||
-
|
||||
- The Initial Developer of the Original Code is the Mozilla Corporation.
|
||||
- Portions created by the Initial Developer are Copyright (C) 2007
|
||||
- the Initial Developer. All Rights Reserved.
|
||||
-
|
||||
- Contributor(s):
|
||||
- Rob Helmer <rhelmer@mozilla.com>
|
||||
- Vladimir Vukicevic <vladimir@mozilla.com>
|
||||
-
|
||||
- Alternatively, the contents of this file may be used under the terms of
|
||||
- either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
- in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
- of those above. If you wish to allow use of your version of this file only
|
||||
- under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
- use your version of this file under the terms of the MPL, indicate your
|
||||
- decision by deleting the provisions above and replace them with the notice
|
||||
- and other provisions required by the LGPL or the GPL. If you do not delete
|
||||
- the provisions above, a recipient may use your version of this file under
|
||||
- the terms of any one of the MPL, the GPL or the LGPL.
|
||||
-
|
||||
- ***** END LICENSE BLOCK ***** -->
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
|
||||
<window
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="pageloader"
|
||||
screenX="0" screenY="0"
|
||||
onload="plInit()">
|
||||
|
||||
<script type="application/x-javascript"
|
||||
src="chrome://global/content/globalOverlay.js"/>
|
||||
<script type="application/x-javascript" src="MozillaFileLogger.js"></script>
|
||||
<script type="application/x-javascript" src="report.js"></script>
|
||||
<script type="application/x-javascript" src="pageloader.js"></script>
|
||||
<script type="application/x-javascript" src="quit.js"></script>
|
||||
<script type="application/x-javascript" src="memory.js"></script>
|
||||
|
||||
<browser id="contentPageloader" src="about:blank"
|
||||
type="content" flex="1"/>
|
||||
</window>
|
|
@ -0,0 +1,110 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is The Original Code is Mozilla Automated Testing Code
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2005
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Bob Clary <bob@bclary.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
From mozilla/toolkit/content
|
||||
These files did not have a license
|
||||
*/
|
||||
|
||||
function canQuitApplication()
|
||||
{
|
||||
var os = Components.classes["@mozilla.org/observer-service;1"]
|
||||
.getService(Components.interfaces.nsIObserverService);
|
||||
if (!os)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"]
|
||||
.createInstance(Components.interfaces.nsISupportsPRBool);
|
||||
os.notifyObservers(cancelQuit, "quit-application-requested", null);
|
||||
|
||||
// Something aborted the quit process.
|
||||
if (cancelQuit.data)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (ex)
|
||||
{
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function goQuitApplication()
|
||||
{
|
||||
if (!canQuitApplication())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const kAppStartup = '@mozilla.org/toolkit/app-startup;1';
|
||||
const kAppShell = '@mozilla.org/appshell/appShellService;1';
|
||||
var appService;
|
||||
var forceQuit;
|
||||
|
||||
if (kAppStartup in Components.classes)
|
||||
{
|
||||
appService = Components.classes[kAppStartup].
|
||||
getService(Components.interfaces.nsIAppStartup);
|
||||
forceQuit = Components.interfaces.nsIAppStartup.eForceQuit;
|
||||
}
|
||||
else if (kAppShell in Components.classes)
|
||||
{
|
||||
appService = Components.classes[kAppShell].
|
||||
getService(Components.interfaces.nsIAppShellService);
|
||||
forceQuit = Components.interfaces.nsIAppShellService.eForceQuit;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw 'goQuitApplication: no AppStartup/appShell';
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
appService.quit(forceQuit);
|
||||
}
|
||||
catch(ex)
|
||||
{
|
||||
throw('goQuitApplication: ' + ex);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
/* 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/. */
|
||||
|
||||
// given an array of strings, finds the longest common prefix
|
||||
function findCommonPrefixLength(strs) {
|
||||
if (strs.length < 2)
|
||||
return 0;
|
||||
|
||||
var len = 0;
|
||||
do {
|
||||
var newlen = len + 1;
|
||||
var newprefix = null;
|
||||
var failed = false;
|
||||
for (var i = 0; i < strs.length; i++) {
|
||||
if (newlen > strs[i].length) {
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
var s = strs[i].substr(0, newlen);
|
||||
if (newprefix == null) {
|
||||
newprefix = s;
|
||||
} else if (newprefix != s) {
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (failed)
|
||||
break;
|
||||
|
||||
len++;
|
||||
} while (true);
|
||||
return len;
|
||||
}
|
||||
|
||||
// Constructor
|
||||
function Report() {
|
||||
this.timeVals = {};
|
||||
this.totalCCTime = 0;
|
||||
this.showTotalCCTime = false;
|
||||
}
|
||||
|
||||
Report.prototype.pageNames = function() {
|
||||
var retval = new Array();
|
||||
for (var page in this.timeVals) {
|
||||
retval.push(page);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
Report.prototype.getReport = function() {
|
||||
|
||||
var report;
|
||||
var pages = this.pageNames();
|
||||
var prefixLen = findCommonPrefixLength(pages);
|
||||
|
||||
report = "__start_tp_report\n";
|
||||
report += "_x_x_mozilla_page_load\n";
|
||||
report += "_x_x_mozilla_page_load_details\n";
|
||||
report += "|i|pagename|runs|\n";
|
||||
|
||||
for (var i=0; i < pages.length; i++) {
|
||||
report += '|'+
|
||||
i + ';'+
|
||||
pages[i].substr(prefixLen) + ';'+
|
||||
this.timeVals[pages[i]].join(";") +
|
||||
"\n";
|
||||
}
|
||||
report += "__end_tp_report\n";
|
||||
|
||||
if (this.showTotalCCTime) {
|
||||
report += "__start_cc_report\n";
|
||||
report += "_x_x_mozilla_cycle_collect," + this.totalCCTime + "\n";
|
||||
report += "__end_cc_report\n";
|
||||
}
|
||||
var now = (new Date()).getTime();
|
||||
report += "__startTimestamp" + now + "__endTimestamp\n"; //timestamp for determning shutdown time, used by talos
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
Report.prototype.recordTime = function(pageName, ms) {
|
||||
if (this.timeVals[pageName] == undefined) {
|
||||
this.timeVals[pageName] = new Array();
|
||||
}
|
||||
this.timeVals[pageName].push(ms);
|
||||
}
|
||||
|
||||
Report.prototype.recordCCTime = function(ms) {
|
||||
this.totalCCTime += ms;
|
||||
this.showTotalCCTime = true;
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is DOM Inspector.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Christopher A. Aillon <christopher@aillon.com>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Christopher A. Aillon <christopher@aillon.com>
|
||||
* L. David Baron, Mozilla Corporation <dbaron@dbaron.org> (modified for reftest)
|
||||
* Vladimir Vukicevic, Mozilla Corporation <dbaron@dbaron.org> (modified for tp)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// This only implements nsICommandLineHandler, since it needs
|
||||
// to handle multiple arguments.
|
||||
|
||||
const TP_CMDLINE_CONTRACTID = "@mozilla.org/commandlinehandler/general-startup;1?type=tp";
|
||||
const TP_CMDLINE_CLSID = Components.ID('{8AF052F5-8EFE-4359-8266-E16498A82E8B}');
|
||||
const CATMAN_CONTRACTID = "@mozilla.org/categorymanager;1";
|
||||
const nsISupports = Components.interfaces.nsISupports;
|
||||
|
||||
const nsICategoryManager = Components.interfaces.nsICategoryManager;
|
||||
const nsICommandLine = Components.interfaces.nsICommandLine;
|
||||
const nsICommandLineHandler = Components.interfaces.nsICommandLineHandler;
|
||||
const nsIComponentRegistrar = Components.interfaces.nsIComponentRegistrar;
|
||||
const nsISupportsString = Components.interfaces.nsISupportsString;
|
||||
const nsIWindowWatcher = Components.interfaces.nsIWindowWatcher;
|
||||
|
||||
function PageLoaderCmdLineHandler() {}
|
||||
PageLoaderCmdLineHandler.prototype =
|
||||
{
|
||||
/* nsISupports */
|
||||
QueryInterface : function handler_QI(iid) {
|
||||
if (iid.equals(nsISupports))
|
||||
return this;
|
||||
|
||||
if (nsICommandLineHandler && iid.equals(nsICommandLineHandler))
|
||||
return this;
|
||||
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
/* nsICommandLineHandler */
|
||||
handle : function handler_handle(cmdLine) {
|
||||
var args = {};
|
||||
try {
|
||||
var uristr = cmdLine.handleFlagWithParam("tp", false);
|
||||
if (uristr == null)
|
||||
return;
|
||||
try {
|
||||
args.manifest = cmdLine.resolveURI(uristr).spec;
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
|
||||
args.numCycles = cmdLine.handleFlagWithParam("tpcycles", false);
|
||||
args.numPageCycles = cmdLine.handleFlagWithParam("tppagecycles", false);
|
||||
args.startIndex = cmdLine.handleFlagWithParam("tpstart", false);
|
||||
args.endIndex = cmdLine.handleFlagWithParam("tpend", false);
|
||||
args.filter = cmdLine.handleFlagWithParam("tpfilter", false);
|
||||
args.useBrowserChrome = cmdLine.handleFlag("tpchrome", false);
|
||||
args.doRender = cmdLine.handleFlag("tprender", false);
|
||||
args.width = cmdLine.handleFlagWithParam("tpwidth", false);
|
||||
args.height = cmdLine.handleFlagWithParam("tpheight", false);
|
||||
args.offline = cmdLine.handleFlag("tpoffline", false);
|
||||
args.noisy = cmdLine.handleFlag("tpnoisy", false);
|
||||
args.timeout = cmdLine.handleFlagWithParam("tptimeout", false);
|
||||
args.delay = cmdLine.handleFlagWithParam("tpdelay", false);
|
||||
args.noForceCC = cmdLine.handleFlag("tpnoforcecc", false);
|
||||
args.mozafterpaint = cmdLine.handleFlag("tpmozafterpaint", false);
|
||||
args.rss = cmdLine.handleFlag("rss", false);
|
||||
}
|
||||
catch (e) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get our data through xpconnect
|
||||
args.wrappedJSObject = args;
|
||||
|
||||
var wwatch = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
|
||||
.getService(nsIWindowWatcher);
|
||||
wwatch.openWindow(null, "chrome://pageloader/content/pageloader.xul", "_blank",
|
||||
"chrome,dialog=no,all", args);
|
||||
cmdLine.preventDefault = true;
|
||||
},
|
||||
|
||||
helpInfo :
|
||||
" -tp <file> Run pageload perf tests on given manifest\n" +
|
||||
" -tpfilter str Only include pages from manifest that contain str (regexp)\n" +
|
||||
" -tpcycles n Loop through pages n times\n" +
|
||||
" -tppagecycles n Loop through each page n times before going onto the next page\n" +
|
||||
" -tpstart n Start at index n in the manifest\n" +
|
||||
" -tpend n End with index n in the manifest\n" +
|
||||
" -tpchrome Test with normal browser chrome\n" +
|
||||
" -tprender Run render-only benchmark for each page\n" +
|
||||
" -tpwidth width Width of window\n" +
|
||||
" -tpheight height Height of window\n" +
|
||||
" -tpoffline Force offline mode\n" +
|
||||
" -tpnoisy Dump the name of the last loaded page to console\n" +
|
||||
" -tptimeout Max amount of time given for a page to load, quit if exceeded\n" +
|
||||
" -tpdelay Amount of time to wait between each pageload\n" +
|
||||
" -tpnoforcecc Don't force cycle collection between each pageload\n" +
|
||||
" -tpmozafterpaint Measure Time after recieving MozAfterPaint event instead of load event\n" +
|
||||
" -rss Dump RSS after each page is loaded\n"
|
||||
|
||||
};
|
||||
|
||||
|
||||
var PageLoaderCmdLineFactory =
|
||||
{
|
||||
createInstance : function(outer, iid)
|
||||
{
|
||||
if (outer != null) {
|
||||
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
||||
}
|
||||
|
||||
return new PageLoaderCmdLineHandler().QueryInterface(iid);
|
||||
}
|
||||
};
|
||||
|
||||
function NSGetFactory(cid) {
|
||||
if (!cid.equals(TP_CMDLINE_CLSID))
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
return PageLoaderCmdLineFactory;
|
||||
}
|
||||
|
||||
var PageLoaderCmdLineModule =
|
||||
{
|
||||
registerSelf : function(compMgr, fileSpec, location, type)
|
||||
{
|
||||
compMgr = compMgr.QueryInterface(nsIComponentRegistrar);
|
||||
|
||||
compMgr.registerFactoryLocation(TP_CMDLINE_CLSID,
|
||||
"PageLoader CommandLine Service",
|
||||
TP_CMDLINE_CONTRACTID,
|
||||
fileSpec,
|
||||
location,
|
||||
type);
|
||||
|
||||
var catman = Components.classes[CATMAN_CONTRACTID].getService(nsICategoryManager);
|
||||
catman.addCategoryEntry("command-line-handler",
|
||||
"m-tp",
|
||||
TP_CMDLINE_CONTRACTID, true, true);
|
||||
},
|
||||
|
||||
unregisterSelf : function(compMgr, fileSpec, location)
|
||||
{
|
||||
compMgr = compMgr.QueryInterface(nsIComponentRegistrar);
|
||||
|
||||
compMgr.unregisterFactoryLocation(TP_CMDLINE_CLSID, fileSpec);
|
||||
catman = Components.classes[CATMAN_CONTRACTID].getService(nsICategoryManager);
|
||||
catman.deleteCategoryEntry("command-line-handler",
|
||||
"m-tp", true);
|
||||
},
|
||||
|
||||
getClassObject : function(compMgr, cid, iid)
|
||||
{
|
||||
return NSGetFactory(cid);
|
||||
},
|
||||
|
||||
canUnload : function(compMgr)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function NSGetModule(compMgr, fileSpec) {
|
||||
return PageLoaderCmdLineModule;
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>pageloader@mozilla.org</em:id>
|
||||
<em:version>1.0</em:version>
|
||||
<em:targetApplication>
|
||||
<Description>
|
||||
<em:id>toolkit@mozilla.org</em:id>
|
||||
<em:minVersion>2.0b3pre</em:minVersion>
|
||||
<em:maxVersion>*</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
<!-- Front End MetaData -->
|
||||
<em:name>PageLoader extension</em:name>
|
||||
<em:description>Cycles through pages and measures load times</em:description>
|
||||
<em:creator>Vladimir Vukicevic</em:creator>
|
||||
</Description>
|
||||
</RDF>
|
Загрузка…
Ссылка в новой задаче