pageloader exgtension for firefox, b=367559 r=robcee

This commit is contained in:
rhelmer%mozilla.com 2007-02-01 20:56:13 +00:00
Родитель bd8172f849
Коммит 7b512dea98
10 изменённых файлов: 389 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,6 @@
all:
zip -r pageloader.xpi chrome chrome.manifest install.rdf
check:
./test/chrome/content/report.js
./test/chrome/content/pageloader.js

Просмотреть файл

@ -0,0 +1,13 @@
This is a pageloader extension for Firefox. It cycles through a list of URLs
specified in a text file by the user (one URL per line), and reports statistics
and raw data about the time each page took to load.
This data is dumped to the console, so the browser.dom.window.dump.enabled pref
(boolean) must be set to "true", and on Windows Firefox must be run with the
"-console" command line switch.
This test is intended to be run standalone from a chrome URL, e.g.:
firefox -chrome chrome://pageloader/content/pageloader.xul
The window will close and the data will be dumped to the console when the
test has completed.

Просмотреть файл

@ -0,0 +1 @@
content pageloader chrome/content/

Просмотреть файл

@ -0,0 +1,3 @@
window {
background-color: #0088CC;
}

Просмотреть файл

@ -0,0 +1,148 @@
var NUM_CYCLES = 5;
var pages;
var pageIndex;
var results;
var start_time;
var end_time;
var cycle;
var report;
function plInit() {
try {
pageIndex = 0;
cycle = 0;
results = new Object();
if (! pages) {
pages = plLoadURLsFromFile();
}
if (pages.length == 0) {
alert('no pages to test');
plStop(true);
}
report = new Report(pages);
plLoadPage();
} catch(e) {
alert(e);
plStop(true);
}
}
function plLoadPage() {
try {
start_time = new Date();
p = pages[pageIndex];
var startButton = document.getElementById('plStartButton');
startButton.setAttribute('disabled', 'true');
this.content = document.getElementById('contentPageloader');
this.content.addEventListener('load', plLoadHandler, true);
this.content.loadURI(p);
} catch (e) {
alert(e);
plStop(true);
}
}
function plLoadHandler(evt) {
if (evt.type == 'load') {
window.setTimeout('reallyHandle()', 500);
} else {
alert('Unknown event type: '+evt.type);
plStop(true);
}
}
function reallyHandle() {
if (pageIndex < pages.length) {
try {
end_time = new Date();
var pageName = pages[pageIndex];
results[pageName] = (end_time - start_time);
start_time = new Date();
dump(pageName+" took "+results[pageName]+"\n");
plReport();
pageIndex++;
plLoadPage();
} catch(e) {
alert(e);
plStop(true);
}
} else {
plStop(false);
}
}
function plReport() {
try {
var reportNode = document.getElementById('report');
var pageName = pages[pageIndex];
var time = results[pageName];
report.recordTime(pageIndex, time);
} catch(e) {
alert(e);
plStop(false);
}
}
function plStop(force) {
try {
pageIndex = 0;
results = new Object;
if (force == false) {
if (cycle < NUM_CYCLES) {
cycle++;
plLoadPage();
return;
} else {
dump(report.getReport()+"\n");
}
}
var startButton = document.getElementById('plStartButton');
startButton.setAttribute('disabled', 'false');
this.content.removeEventListener('load', plLoadHandler, true);
//goQuitApplication();
} catch(e) {
alert(e);
}
}
/* Returns array */
function plLoadURLsFromFile() {
try {
const nsIFilePicker = Components.interfaces.nsIFilePicker;
var fp = Components.classes["@mozilla.org/filepicker;1"]
.createInstance(nsIFilePicker);
fp.init(window, "Dialog Title", nsIFilePicker.modeOpen);
fp.appendFilters(nsIFilePicker.filterAll | nsIFilePicker.filterText);
var rv = fp.show();
if (rv == nsIFilePicker.returnOK)
{
var file = fp.file;
var data = "";
var fstream =
Components.classes["@mozilla.org/network/file-input-stream;1"]
.createInstance(Components.interfaces.nsIFileInputStream);
var sstream = Components.classes["@mozilla.org/scriptableinputstream;1"]
.createInstance(Components.interfaces.nsIScriptableInputStream);
fstream.init(file, -1, 0, 0);
sstream.init(fstream);
var str = sstream.read(4096);
while (str.length > 0) {
data += str;
str = sstream.read(4096);
}
sstream.close();
fstream.close();
var p = data.split("\n");
// discard result of final split (EOF)
p.pop()
return p;
}
} catch (e) {
alert(e);
}
}

Просмотреть файл

@ -0,0 +1,14 @@
<?xml version="1.0"?>
<?xml-stylesheet href="pageloader.css" type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/x-javascript" src="chrome://global/content/globalOverlay.js"/>
<script type="application/x-javascript" src="report.js"></script>
<script type="application/x-javascript" src="pageloader.js"></script>
<box align="center">
<button id="plStartButton" label="start" onclick="plInit(false);" />
</box>
<box align="center">
<browser id="contentPageloader" src="about:blank"
type="content" flex="1" align="center" width="1024" height="768"/>
</box>
</window>

Просмотреть файл

@ -0,0 +1,112 @@
// Constructor
function Report(pages) {
this.pages = pages;
this.timeVals = new Array(pages.length); // matrix of times
for (var i = 0; i < this.timeVals.length; ++i) {
this.timeVals[i] = new Array;
}
}
// returns an object with the following properties:
// min : min value of array elements
// max : max value of array elements
// mean : mean value of array elements
// vari : variance computation
// stdd : standard deviation, sqrt(vari)
// indexOfMax : index of max element (the element that is
// removed from the mean computation)
Report.prototype.getArrayStats = function(ary) {
var r = {};
r.min = ary[0];
r.max = ary[0];
r.indexOfMax = 0;
var sum = 0;
for (var i = 0; i < ary.length; ++i) {
if (ary[i] < r.min) {
r.min = ary[i];
} else if (ary[i] > r.max) {
r.max = ary[i];
r.indexOfMax = i;
}
sum = sum + ary[i];
}
// median
sorted_ary = ary.concat();
sorted_ary.sort();
// remove longest run
sorted_ary.pop();
if (sorted_ary.length%2) {
r.median = sorted_ary[(sorted_ary.length-1)/2];
}else{
var n = Math.floor(sorted_ary.length / 2);
r.median = (sorted_ary[n] + sorted_ary[n + 1]) / 2;
}
// ignore max value when computing mean and stddev
r.mean = (sum - r.max) / (ary.length - 1);
r.vari = 0;
for (var i = 0; i < ary.length; ++i) {
if (i == r.indexOfMax)
continue;
var d = r.mean - ary[i];
r.vari = r.vari + d * d;
}
r.vari = r.vari / (ary.length - 1);
r.stdd = Math.sqrt(r.vari);
return r;
}
Report.prototype.getReport = function() {
var all = new Array();
var counter = 0;
for (var i = 0; i < this.timeVals.length; ++i) {
for (var j = 0; j < this.timeVals[i].length; ++j) {
all[counter] = this.timeVals[i][j];
++counter;
}
}
// avg and avg median are cumulative for all the pages
var avgs = new Array();
var medians = new Array();
for (var i = 0; i < this.timeVals.length; ++i) {
avgs[i] = this.getArrayStats(this.timeVals[i]).mean;
medians[i] = this.getArrayStats(this.timeVals[i]).median;
}
var avg = this.getArrayStats(avgs).mean;
var avgmed = this.getArrayStats(medians).mean;
var r = this.getArrayStats(all);
var report = '';
report +=
"(tinderbox dropping follows)\n"+
"_x_x_mozilla_page_load,"+avgmed+","+r.max+","+r.min+"\n"+
"_x_x_mozilla_page_load_details,avgmedian|"+avgmed+"|average|"+avg.toFixed(2)+"|minimum|"+r.min+"|maximum|"+r.max+"|stddev|"+r.stdd.toFixed(2)+":"
for (var i = 0; i < this.timeVals.length; ++i) {
r = this.getArrayStats(this.timeVals[i]);
report +=
'|'+
i+';'+
pages[i]+';'+
r.median+';'+
r.mean+';'+
r.min+';'+
r.max
for (var j = 0; j < this.timeVals[i].length; ++j) {
report +=
';'+this.timeVals[i][j]
}
}
return report;
}
Report.prototype.recordTime = function(pageIndex, ms) {
this.timeVals[pageIndex].push(ms);
}

Просмотреть файл

@ -0,0 +1,27 @@
<?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>0.5</em:version>
<em:type>2</em:type>
<!-- Target Application this extension can install into,
with minimum and maximum supported versions. -->
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>1.0+</em:minVersion>
<em:maxVersion>4.0</em:maxVersion>
</Description>
</em:targetApplication>
<!-- Front End MetaData -->
<em:name>PageLoader</em:name>
<em:description>A pageloader extension.</em:description>
<em:creator>Robert Helmer</em:creator>
<em:homepageURL>http://www.roberthelmer.com/</em:homepageURL>
</Description>
</RDF>

Просмотреть файл

@ -0,0 +1,46 @@
#!/usr/bin/js
// mock objects
function alert(str) {
print(str);
}
function dump(str) {
print(str);
}
window = new Object();
document = new Object();
document.createEvent = function(str) {
obj = new Object();
obj.initMouseEvent = function() {}
return obj;
}
document.getElementById = function(str) {
obj = new Object();
if (str == 'contentPageloader') {
obj.content = new Object();
obj.content.addEventListener = function() {}
obj.content.removeEventListener = function() {}
obj.content.loadURI = function() {}
return obj.content;
} else if (str == 'plStartButton') {
obj.startButton = new Object();
obj.startButton.setAttribute = function(key, value) {}
return obj.startButton;
}
}
evt = new Object();
evt.type = 'load';
window.setTimeout = function() {}
this.content = document.getElementById('content');
// dummy data
pages = ['http://google.com'];
load(['chrome/content/pageloader.js']);
load(['chrome/content/report.js']);
plInit(true);
plInit(false);
for (cycle = 0; cycle < NUM_CYCLES*2; cycle++) {
plLoadHandler(evt);
}

Просмотреть файл

@ -0,0 +1,19 @@
#!/usr/bin/js
load(['chrome/content/report.js']);
pages = [
'http://www.google.com',
'http://www.yahoo.com',
'http://www.msn.com',
];
cycle_time = 5;
report = new Report(pages);
for (var c=0; c < cycle_time; c++) {
for (var p=0; p < pages.length; p++) {
report.recordTime(p, c+1);
}
}
print(report.getReport());