Source code

Revision control

Copy as Markdown

Other Tools

/* 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.every(str => str.includes("/pdfs/"))) {
// In all cases for pdfpaint PDFs, return the full file name
return strs[0].lastIndexOf("/") + 1;
}
if (strs.length < 2) {
// only one page in the manifest
var place = strs[0].lastIndexOf("/");
if (place < 0) {
place = 0;
}
return place;
}
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 = [];
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++) {
// don't report any measurements that were reported for about:blank
// some tests (like about-preferences) use it as a dummy test page
if (pages[i] == "about:blank") {
continue;
}
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 = window.performance.now();
report += "__startTimestamp" + now + "__endTimestamp\n"; // timestamp for determning shutdown time, used by talos
return report;
};
Report.prototype.getReportSummary = function () {
function average(arr) {
var sum = 0;
for (var i in arr) {
sum += arr[i];
}
return sum / (arr.length || 1);
}
function median(arr) {
if (!arr.length) {
return 0;
} // As good indication for "not available" as any other value.
var sorted = arr.slice(0).sort();
var mid = Math.floor(arr.length / 2);
if (sorted.length % 2) {
return sorted[mid];
}
return average(sorted.slice(mid, mid + 2));
}
// We use sample stddev and not population stddev because
// well.. it's a sample and we can't collect all/infinite number of values.
function stddev(arr) {
if (arr.length <= 1) {
return 0;
}
var avg = average(arr);
var squareDiffArr = arr.map(function (v) {
return Math.pow(v - avg, 2);
});
var sum = squareDiffArr.reduce(function (a, b) {
return a + b;
});
var rv = Math.sqrt(sum / (arr.length - 1));
return rv;
}
var report = "";
var pages = this.pageNames();
var prefixLen = findCommonPrefixLength(pages);
report += "------- Summary: start -------\n";
report += "Number of tests: " + pages.length + "\n";
for (var i = 0; i < pages.length; i++) {
var results = this.timeVals[pages[i]].map(function (v) {
return Number(v);
});
report +=
"\n[#" +
i +
"] " +
pages[i].substr(prefixLen) +
" Cycles:" +
results.length +
" Average:" +
average(results).toFixed(2) +
" Median:" +
median(results).toFixed(2) +
" stddev:" +
stddev(results).toFixed(2) +
" (" +
((100 * stddev(results)) / median(results)).toFixed(1) +
"%)" +
(results.length < 5
? ""
: " stddev-sans-first:" + stddev(results.slice(1)).toFixed(2)) +
"\nValues: " +
results
.map(function (v) {
return v.toFixed(1);
})
.join(" ") +
"\n";
}
report += "-------- Summary: end --------\n";
return report;
};
Report.prototype.recordTime = function (pageName, ms) {
if (this.timeVals[pageName] == undefined) {
this.timeVals[pageName] = [];
}
this.timeVals[pageName].push(ms);
};
Report.prototype.recordCCTime = function (ms) {
this.totalCCTime += ms;
this.showTotalCCTime = true;
};