You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
244 lines
6.8 KiB
244 lines
6.8 KiB
<script type="text/ecmascript"> |
|
function init() { |
|
var x = document.getElementsByTagName("svg") |
|
for (i = 0; i < x.length; i=i+1) { |
|
createZoomHistoryStack(x[i]); |
|
} |
|
} |
|
|
|
// Create a stack add the root svg element in it. |
|
function createZoomHistoryStack(svgElement) { |
|
stack = []; |
|
svgElement.zoomStack = stack; |
|
stack.push(svgElement.getElementById(svgElement.attributes["rootid"].value)) |
|
} |
|
|
|
function dumpStack(svgElement) { |
|
// Disable (enable for debugging) |
|
return |
|
stack = svgElement.zoomStack; |
|
for (i=0 ; i < stack.length; i++) { |
|
title = stack[i].getElementsByTagName("title")[0]; |
|
console.log("[" +i+ "]-" + title.textContent) |
|
} |
|
} |
|
|
|
function adjust_node_text_size(x) { |
|
title = x.getElementsByTagName("title")[0]; |
|
text = x.getElementsByTagName("text")[0]; |
|
rect = x.getElementsByTagName("rect")[0]; |
|
|
|
width = parseFloat(rect.attributes["width"].value); |
|
|
|
// Don't even bother trying to find a best fit. The area is too small. |
|
if (width < 25) { |
|
text.textContent = ""; |
|
return; |
|
} |
|
// Remove dso and #samples which are here only for mouseover purposes. |
|
methodName = title.textContent.substring(0, title.textContent.indexOf("|")); |
|
|
|
var numCharacters; |
|
for (numCharacters=methodName.length; numCharacters>4; numCharacters--) { |
|
// Avoid reflow by using hard-coded estimate instead of text.getSubStringLength(0, numCharacters) |
|
// if (text.getSubStringLength(0, numCharacters) <= width) { |
|
if (numCharacters * 7.5 <= width) { |
|
break ; |
|
} |
|
} |
|
|
|
if (numCharacters == methodName.length) { |
|
text.textContent = methodName; |
|
return |
|
} |
|
|
|
text.textContent = methodName.substring(0, numCharacters-2) + ".."; |
|
} |
|
|
|
function adjust_text_size(svgElement) { |
|
var x = svgElement.getElementsByTagName("g"); |
|
var i; |
|
for (i=0 ; i < x.length ; i=i+1) { |
|
adjust_node_text_size(x[i]) |
|
} |
|
} |
|
|
|
function zoom(e) { |
|
svgElement = e.ownerSVGElement |
|
zoomStack = svgElement.zoomStack; |
|
zoomStack.push(e); |
|
displayFromElement(e) |
|
select(e); |
|
dumpStack(e.ownerSVGElement); |
|
|
|
// Show zoom out button. |
|
svgElement.getElementById("zoom_rect").style.display = "block"; |
|
svgElement.getElementById("zoom_text").style.display = "block"; |
|
} |
|
|
|
function displayFromElement(e) { |
|
var clicked_rect = e.getElementsByTagName("rect")[0]; |
|
var clicked_origin_x = clicked_rect.attributes["ox"].value; |
|
var clicked_origin_y = clicked_rect.attributes["oy"].value; |
|
var clicked_origin_width = clicked_rect.attributes["owidth"].value; |
|
|
|
|
|
var svgBox = e.ownerSVGElement.getBoundingClientRect(); |
|
var svgBoxHeight = svgBox.height |
|
var svgBoxWidth = svgBox.width |
|
var scaleFactor = svgBoxWidth/clicked_origin_width; |
|
|
|
var callsites = e.ownerSVGElement.getElementsByTagName("g"); |
|
var i; |
|
for (i = 0; i < callsites.length; i=i+1) { |
|
text = callsites[i].getElementsByTagName("text")[0]; |
|
rect = callsites[i].getElementsByTagName("rect")[0]; |
|
|
|
rect_o_x = rect.attributes["ox"].value |
|
rect_o_y = parseFloat(rect.attributes["oy"].value) |
|
|
|
// Avoid multiple forced reflow by hiding nodes. |
|
if (rect_o_y > clicked_origin_y) { |
|
rect.style.display = "none" |
|
text.style.display = "none" |
|
continue; |
|
} else { |
|
rect.style.display = "block" |
|
text.style.display = "block" |
|
} |
|
|
|
rect.attributes["x"].value = newrec_x = (rect_o_x - clicked_origin_x) * scaleFactor ; |
|
rect.attributes["y"].value = newrec_y = rect_o_y + (svgBoxHeight - clicked_origin_y - 17 -2); |
|
|
|
text.attributes["y"].value = newrec_y + 12; |
|
text.attributes["x"].value = newrec_x + 4; |
|
|
|
rect.attributes["width"].value = rect.attributes["owidth"].value * scaleFactor; |
|
} |
|
|
|
adjust_text_size(e.ownerSVGElement); |
|
|
|
} |
|
|
|
function unzoom(e) { |
|
|
|
var svgOwner = e.ownerSVGElement; |
|
stack = svgOwner.zoomStack; |
|
|
|
// Unhighlight whatever was selected. |
|
if (selected != null) |
|
selected.classList.remove("s") |
|
|
|
|
|
// Stack management: Never remove the last element which is the flamegraph root. |
|
if (stack.length > 1) { |
|
previouslySelected = stack.pop(); |
|
select(previouslySelected); |
|
} |
|
nextElement = stack[stack.length-1] // stack.peek() |
|
|
|
// Hide zoom out button. |
|
if (stack.length==1) { |
|
svgOwner.getElementById("zoom_rect").style.display = "none"; |
|
svgOwner.getElementById("zoom_text").style.display = "none"; |
|
} |
|
|
|
displayFromElement(nextElement); |
|
dumpStack(svgOwner); |
|
} |
|
|
|
function search(e) { |
|
var term = prompt("Search for:", ""); |
|
|
|
var svgOwner = e.ownerSVGElement |
|
var callsites = e.ownerSVGElement.getElementsByTagName("g"); |
|
|
|
if (term == null || term == "") { |
|
for (i = 0; i < callsites.length; i=i+1) { |
|
rect = callsites[i].getElementsByTagName("rect")[0]; |
|
rect.attributes["fill"].value = rect.attributes["ofill"].value; |
|
} |
|
return; |
|
} |
|
|
|
for (i = 0; i < callsites.length; i=i+1) { |
|
title = callsites[i].getElementsByTagName("title")[0]; |
|
rect = callsites[i].getElementsByTagName("rect")[0]; |
|
if (title.textContent.indexOf(term) != -1) { |
|
rect.attributes["fill"].value = "rgb(230,100,230)"; |
|
} else { |
|
rect.attributes["fill"].value = rect.attributes["ofill"].value; |
|
} |
|
} |
|
} |
|
|
|
var selected; |
|
document.onkeydown = function handle_keyboard_input(e) { |
|
if (selected == null) |
|
return; |
|
|
|
title = selected.getElementsByTagName("title")[0]; |
|
nav = selected.attributes["nav"].value.split(",") |
|
navigation_index = -1 |
|
switch (e.keyCode) { |
|
//case 38: // ARROW UP |
|
case 87 : navigation_index = 0;break; //W |
|
|
|
//case 32 : // ARROW LEFT |
|
case 65 : navigation_index = 1;break; //A |
|
|
|
// case 43: // ARROW DOWN |
|
case 68 : navigation_index = 3;break; // S |
|
|
|
// case 39: // ARROW RIGHT |
|
case 83 : navigation_index = 2;break; // D |
|
|
|
case 32 : zoom(selected); return false; break; // SPACE |
|
|
|
case 8: // BACKSPACE |
|
unzoom(selected); return false; |
|
default: return true; |
|
} |
|
|
|
if (nav[navigation_index] == "0") |
|
return false; |
|
|
|
target_element = selected.ownerSVGElement.getElementById(nav[navigation_index]); |
|
select(target_element) |
|
return false; |
|
} |
|
|
|
function select(e) { |
|
if (selected != null) |
|
selected.classList.remove("s") |
|
selected = e; |
|
selected.classList.add("s") |
|
|
|
// Update info bar |
|
titleElement = selected.getElementsByTagName("title")[0]; |
|
text = titleElement.textContent; |
|
|
|
// Parse title |
|
method_and_info = text.split(" | "); |
|
methodName = method_and_info[0]; |
|
info = method_and_info[1] |
|
|
|
// Parse info |
|
// '/system/lib64/libhwbinder.so (4 samples: 0.28%)' |
|
var regexp = /(.*) \(.* ([0-9**\.[0-9]*%)\)/g; |
|
match = regexp.exec(info); |
|
if (match.length > 2) { |
|
percentage = match[2] |
|
// Write percentage |
|
percentageTextElement = selected.ownerSVGElement.getElementById("percent_text") |
|
percentageTextElement.textContent = percentage |
|
//console.log("'" + percentage + "'") |
|
} |
|
|
|
// Set fields |
|
barTextElement = selected.ownerSVGElement.getElementById("info_text") |
|
barTextElement.textContent = methodName |
|
} |
|
|
|
|
|
</script> |