Skip to content
This repository has been archived by the owner on May 5, 2022. It is now read-only.

Commit

Permalink
Show the child hangs in a different color to make them stand out more.
Browse files Browse the repository at this point in the history
  • Loading branch information
Uberi committed Jan 27, 2016
1 parent 5572a2d commit 5498a11
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 17 deletions.
5 changes: 4 additions & 1 deletion data/panel.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@
color: white;
z-index: 1;
}
.childHang .controls {
background: #5555AA;
}
.controls .duration {
font-size: 12px;
}
Expand Down Expand Up @@ -127,6 +130,6 @@ <h1>MOST RECENT HANGS</h1>
</div>
</div>-->
</div>
<p class="note">Hang uptimes correspond to the X axis in the <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Performance/Profiling_with_the_Built-in_Profiler" target="_blank">Gecko Profiler addon</a> timeline.</p>
<p class="note">Entries with a grey sidebar are parent process hangs, while entries with a blue sidebar are child process hangs. Hang uptimes correspond to the X axis in the <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Performance/Profiling_with_the_Built-in_Profiler" target="_blank">Gecko Profiler addon</a> timeline.</p>
</body>
</html>
3 changes: 3 additions & 0 deletions data/panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ function setHangs(hangs) {
hangs.reverse().forEach(hang => {
// create an entry for the hang
var entry = document.createElement("div");
if (hang.isChild) {
entry.className = "childHang";
}
var contents = document.createElement("pre");
contents.className = "stack";
contents.appendChild(document.createTextNode(hang.stack));
Expand Down
36 changes: 20 additions & 16 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ function getChildThreadHangs() {

// returns the number of Gecko hangs, and the computed minimum threshold for those hangs (which is a value >= gHangThreshold)
function getHangs() {
var hangsPromise;
switch(gMode) {
case "threadHangs":
return numGeckoThreadHangs();
Expand Down Expand Up @@ -192,9 +191,9 @@ function numGeckoThreadHangs(includeChildHangs = true) {
// accumulate all of the counts in the child processes with the counts in the parent process
let counts = geckoThread.activity.counts.slice(0);
hangs.forEach((threadHangStats) => {
let geckoThread = threadHangStats.find(thread => thread.name == "Gecko_Child");
if (geckoThread && geckoThread.activity.counts) {
geckoThread.activity.counts.forEach((count, i) => { counts[i] += count; });
let childGeckoThread = threadHangStats.find(thread => thread.name == "Gecko_Child");
if (childGeckoThread && childGeckoThread.activity.counts) {
childGeckoThread.activity.counts.forEach((count, i) => { counts[i] += count; });
}
});
resolve(counts);
Expand Down Expand Up @@ -279,27 +278,29 @@ function mostRecentHangs(includeChildHangs = true) {
if (includeChildHangs) {
getChildThreadHangs().then((hangs) => {
// accumulate all of the counts in the child processes with the counts in the parent process
let hangEntries = geckoThread.hangs.slice(0);
let childHangEntries = [];
hangs.forEach((threadHangStats) => {
let geckoThread = threadHangStats.find(thread => thread.name == "Gecko_Child");
if (geckoThread && geckoThread.activity.counts) {
hangEntries = hangEntries.concat(geckoThread.hangs);
let childGeckoThread = threadHangStats.find(thread => thread.name == "Gecko_Child");
if (childGeckoThread && childGeckoThread.activity.counts) {
childHangEntries = childHangEntries.concat(childGeckoThread.hangs);
}
});
resolve(hangEntries);
resolve([geckoThread.hangs, childHangEntries]);
});
} else { // Just use the parent process stats
resolve(geckoThread.hangs);
resolve([geckoThread.hangs, []]);
}
}).then((hangEntries) => {
var timestamp = (new Date()).getTime(); // note that this timestamp will only be as accurate as the interval at which this function is called
var uptime = getUptime(); // this value matches the X axis in the timeline for the Gecko Profiler addon
}).then(hangInfo => {
[hangEntries, childHangEntries] = hangInfo;
console.error(childHangEntries)
let timestamp = (new Date()).getTime(); // note that this timestamp will only be as accurate as the interval at which this function is called
let uptime = getUptime(); // this value matches the X axis in the timeline for the Gecko Profiler addon

// diff the current hangs with the previous hangs to figure out what changed in this call, if anything
// hangs list will only ever grow: https://dxr.mozilla.org/mozilla-central/source/xpcom/threads/BackgroundHangMonitor.cpp#440
// therefore, we only need to check current stacks against previous stacks - there is no need for a 2 way diff
// hangs are identified by their stack traces: https://dxr.mozilla.org/mozilla-central/source/toolkit/components/telemetry/Telemetry.cpp#4316
hangEntries.forEach(hangEntry => {
function diffHangEntry(hangEntry, isChild) {
var stack = hangEntry.stack.slice(0).reverse().join("\n");
var ranges = hangEntry.histogram.ranges.concat([Infinity]);
var counts = hangEntry.histogram.counts;
Expand All @@ -324,6 +325,7 @@ function mostRecentHangs(includeChildHangs = true) {
cachedRecentHangs.push({
stack: stack, lowerBound: lowerBound, upperBound: ranges[i],
timestamp: timestamp, uptime: uptime, previousUptime: lastMostRecentHangsTime,
isChild: isChild,
});
if (cachedRecentHangs.length > 10) { // only keep the last 10 items
cachedRecentHangs.shift();
Expand All @@ -336,7 +338,9 @@ function mostRecentHangs(includeChildHangs = true) {
// the hang entry is not mutated when new instances of this hang come in
// since we aren't using this entry in the previous hangs anymore, we can just set it in the previous hangs
previousCountsMap[stack] = counts;
});
}
hangEntries.forEach(entry => { diffHangEntry(entry, false); });
childHangEntries.forEach(entry => { diffHangEntry(entry, true); });
lastMostRecentHangsTime = uptime;
return cachedRecentHangs;
});
Expand Down Expand Up @@ -407,7 +411,7 @@ function update() {
mostRecentHangs().then((recentHangs) => {
panel.port.emit("set-hangs", recentHangs);
if (recentHangs.length > 0) {
button.label = "Most recent hang stack:\n\n" + hangs[hangs.length - 1].stack;
button.label = "Most recent hang stack:\n\n" + recentHangs[recentHangs.length - 1].stack;
} else {
button.label = "No recent hang stacks.";
}
Expand Down

0 comments on commit 5498a11

Please sign in to comment.