|
<?xml version="1.0" standalone="no"?> |
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> |
|
<svg version="1.1" width="1200" height="262" onload="init(evt)" viewBox="0 0 1200 262" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> |
|
<style type="text/css"> |
|
text { font-family:Verdana; font-size:12px; fill:black; } |
|
.func_g:hover { stroke:black; stroke-width:0.5; cursor:pointer; } |
|
</style> |
|
<script type="text/ecmascript"> |
|
<![CDATA[ |
|
var details, searchbtn, matchedtxt, svg; |
|
function init(evt) { |
|
details = document.getElementById("details").firstChild; |
|
searchbtn = document.getElementById("search"); |
|
matchedtxt = document.getElementById("matched"); |
|
svg = document.getElementsByTagName("svg")[0]; |
|
searching = 0; |
|
} |
|
|
|
// mouse-over for info |
|
function s(node) { // show |
|
info = g_to_text(node); |
|
details.nodeValue = "Function: " + info; |
|
} |
|
function c() { // clear |
|
details.nodeValue = ' '; |
|
} |
|
|
|
// ctrl-F for search |
|
window.addEventListener("keydown",function (e) { |
|
if (e.keyCode === 114 || (e.ctrlKey && e.keyCode === 70)) { |
|
e.preventDefault(); |
|
search_prompt(); |
|
} |
|
}) |
|
|
|
// functions |
|
function find_child(parent, name, attr) { |
|
var children = parent.childNodes; |
|
for (var i=0; i<children.length;i++) { |
|
if (children[i].tagName == name) |
|
return (attr != undefined) ? children[i].attributes[attr].value : children[i]; |
|
} |
|
return; |
|
} |
|
function orig_save(e, attr, val) { |
|
if (e.attributes["_orig_"+attr] != undefined) return; |
|
if (e.attributes[attr] == undefined) return; |
|
if (val == undefined) val = e.attributes[attr].value; |
|
e.setAttribute("_orig_"+attr, val); |
|
} |
|
function orig_load(e, attr) { |
|
if (e.attributes["_orig_"+attr] == undefined) return; |
|
e.attributes[attr].value = e.attributes["_orig_"+attr].value; |
|
e.removeAttribute("_orig_"+attr); |
|
} |
|
function g_to_text(e) { |
|
var text = find_child(e, "title").firstChild.nodeValue; |
|
return (text) |
|
} |
|
function g_to_func(e) { |
|
var func = g_to_text(e); |
|
// if there's any manipulation we want to do to the function |
|
// name before it's searched, do it here before returning. |
|
return (func); |
|
} |
|
function update_text(e) { |
|
var r = find_child(e, "rect"); |
|
var t = find_child(e, "text"); |
|
var w = parseFloat(r.attributes["width"].value) -3; |
|
var txt = find_child(e, "title").textContent.replace(/\([^(]*\)$/,""); |
|
t.attributes["x"].value = parseFloat(r.attributes["x"].value) +3; |
|
|
|
// Smaller than this size won't fit anything |
|
if (w < 2*12*0.59) { |
|
t.textContent = ""; |
|
return; |
|
} |
|
|
|
t.textContent = txt; |
|
// Fit in full text width |
|
if (/^ *$/.test(txt) || t.getSubStringLength(0, txt.length) < w) |
|
return; |
|
|
|
for (var x=txt.length-2; x>0; x--) { |
|
if (t.getSubStringLength(0, x+2) <= w) { |
|
t.textContent = txt.substring(0,x) + ".."; |
|
return; |
|
} |
|
} |
|
t.textContent = ""; |
|
} |
|
|
|
// zoom |
|
function zoom_reset(e) { |
|
if (e.attributes != undefined) { |
|
orig_load(e, "x"); |
|
orig_load(e, "width"); |
|
} |
|
if (e.childNodes == undefined) return; |
|
for(var i=0, c=e.childNodes; i<c.length; i++) { |
|
zoom_reset(c[i]); |
|
} |
|
} |
|
function zoom_child(e, x, ratio) { |
|
if (e.attributes != undefined) { |
|
if (e.attributes["x"] != undefined) { |
|
orig_save(e, "x"); |
|
e.attributes["x"].value = (parseFloat(e.attributes["x"].value) - x - 10) * ratio + 10; |
|
if(e.tagName == "text") e.attributes["x"].value = find_child(e.parentNode, "rect", "x") + 3; |
|
} |
|
if (e.attributes["width"] != undefined) { |
|
orig_save(e, "width"); |
|
e.attributes["width"].value = parseFloat(e.attributes["width"].value) * ratio; |
|
} |
|
} |
|
|
|
if (e.childNodes == undefined) return; |
|
for(var i=0, c=e.childNodes; i<c.length; i++) { |
|
zoom_child(c[i], x-10, ratio); |
|
} |
|
} |
|
function zoom_parent(e) { |
|
if (e.attributes) { |
|
if (e.attributes["x"] != undefined) { |
|
orig_save(e, "x"); |
|
e.attributes["x"].value = 10; |
|
} |
|
if (e.attributes["width"] != undefined) { |
|
orig_save(e, "width"); |
|
e.attributes["width"].value = parseInt(svg.width.baseVal.value) - (10*2); |
|
} |
|
} |
|
if (e.childNodes == undefined) return; |
|
for(var i=0, c=e.childNodes; i<c.length; i++) { |
|
zoom_parent(c[i]); |
|
} |
|
} |
|
function zoom(node) { |
|
var attr = find_child(node, "rect").attributes; |
|
var width = parseFloat(attr["width"].value); |
|
var xmin = parseFloat(attr["x"].value); |
|
var xmax = parseFloat(xmin + width); |
|
var ymin = parseFloat(attr["y"].value); |
|
var ratio = (svg.width.baseVal.value - 2*10) / width; |
|
|
|
// XXX: Workaround for JavaScript float issues (fix me) |
|
var fudge = 0.0001; |
|
|
|
var unzoombtn = document.getElementById("unzoom"); |
|
unzoombtn.style["opacity"] = "1.0"; |
|
|
|
var el = document.getElementsByTagName("g"); |
|
for(var i=0;i<el.length;i++){ |
|
var e = el[i]; |
|
var a = find_child(e, "rect").attributes; |
|
var ex = parseFloat(a["x"].value); |
|
var ew = parseFloat(a["width"].value); |
|
// Is it an ancestor |
|
if (0 == 0) { |
|
var upstack = parseFloat(a["y"].value) > ymin; |
|
} else { |
|
var upstack = parseFloat(a["y"].value) < ymin; |
|
} |
|
if (upstack) { |
|
// Direct ancestor |
|
if (ex <= xmin && (ex+ew+fudge) >= xmax) { |
|
e.style["opacity"] = "0.5"; |
|
zoom_parent(e); |
|
e.onclick = function(e){unzoom(); zoom(this);}; |
|
update_text(e); |
|
} |
|
// not in current path |
|
else |
|
e.style["display"] = "none"; |
|
} |
|
// Children maybe |
|
else { |
|
// no common path |
|
if (ex < xmin || ex + fudge >= xmax) { |
|
e.style["display"] = "none"; |
|
} |
|
else { |
|
zoom_child(e, xmin, ratio); |
|
e.onclick = function(e){zoom(this);}; |
|
update_text(e); |
|
} |
|
} |
|
} |
|
} |
|
function unzoom() { |
|
var unzoombtn = document.getElementById("unzoom"); |
|
unzoombtn.style["opacity"] = "0.0"; |
|
|
|
var el = document.getElementsByTagName("g"); |
|
for(i=0;i<el.length;i++) { |
|
el[i].style["display"] = "block"; |
|
el[i].style["opacity"] = "1"; |
|
zoom_reset(el[i]); |
|
update_text(el[i]); |
|
} |
|
} |
|
|
|
// search |
|
function reset_search() { |
|
var el = document.getElementsByTagName("rect"); |
|
for (var i=0; i < el.length; i++) { |
|
orig_load(el[i], "fill") |
|
} |
|
} |
|
function search_prompt() { |
|
if (!searching) { |
|
var term = prompt("Enter a search term (regexp " + |
|
"allowed, eg: ^ext4_)", ""); |
|
if (term != null) { |
|
search(term) |
|
} |
|
} else { |
|
reset_search(); |
|
searching = 0; |
|
searchbtn.style["opacity"] = "0.1"; |
|
searchbtn.firstChild.nodeValue = "Search" |
|
matchedtxt.style["opacity"] = "0.0"; |
|
matchedtxt.firstChild.nodeValue = "" |
|
} |
|
} |
|
function search(term) { |
|
var re = new RegExp(term); |
|
var el = document.getElementsByTagName("g"); |
|
var matches = new Object(); |
|
var maxwidth = 0; |
|
for (var i = 0; i < el.length; i++) { |
|
var e = el[i]; |
|
if (e.attributes["class"].value != "func_g") |
|
continue; |
|
var func = g_to_func(e); |
|
var rect = find_child(e, "rect"); |
|
if (rect == null) { |
|
// the rect might be wrapped in an anchor |
|
// if nameattr href is being used |
|
if (rect = find_child(e, "a")) { |
|
rect = find_child(r, "rect"); |
|
} |
|
} |
|
if (func == null || rect == null) |
|
continue; |
|
|
|
// Save max width. Only works as we have a root frame |
|
var w = parseFloat(rect.attributes["width"].value); |
|
if (w > maxwidth) |
|
maxwidth = w; |
|
|
|
if (func.match(re)) { |
|
// highlight |
|
var x = parseFloat(rect.attributes["x"].value); |
|
orig_save(rect, "fill"); |
|
rect.attributes["fill"].value = |
|
"rgb(230,0,230)"; |
|
|
|
// remember matches |
|
if (matches[x] == undefined) { |
|
matches[x] = w; |
|
} else { |
|
if (w > matches[x]) { |
|
// overwrite with parent |
|
matches[x] = w; |
|
} |
|
} |
|
searching = 1; |
|
} |
|
} |
|
if (!searching) |
|
return; |
|
|
|
searchbtn.style["opacity"] = "1.0"; |
|
searchbtn.firstChild.nodeValue = "Reset Search" |
|
|
|
// calculate percent matched, excluding vertical overlap |
|
var count = 0; |
|
var lastx = -1; |
|
var lastw = 0; |
|
var keys = Array(); |
|
for (k in matches) { |
|
if (matches.hasOwnProperty(k)) |
|
keys.push(k); |
|
} |
|
// sort the matched frames by their x location |
|
// ascending, then width descending |
|
keys.sort(function(a, b){ |
|
return a - b; |
|
}); |
|
// Step through frames saving only the biggest bottom-up frames |
|
// thanks to the sort order. This relies on the tree property |
|
// where children are always smaller than their parents. |
|
var fudge = 0.0001; // JavaScript floating point |
|
for (var k in keys) { |
|
var x = parseFloat(keys[k]); |
|
var w = matches[keys[k]]; |
|
if (x >= lastx + lastw - fudge) { |
|
count += w; |
|
lastx = x; |
|
lastw = w; |
|
} |
|
} |
|
// display matched percent |
|
matchedtxt.style["opacity"] = "1.0"; |
|
pct = 100 * count / maxwidth; |
|
if (pct == 100) |
|
pct = "100" |
|
else |
|
pct = pct.toFixed(1) |
|
matchedtxt.firstChild.nodeValue = "Matched: " + pct + "%"; |
|
} |
|
function searchover(e) { |
|
searchbtn.style["opacity"] = "1.0"; |
|
} |
|
function searchout(e) { |
|
if (searching) { |
|
searchbtn.style["opacity"] = "1.0"; |
|
} else { |
|
searchbtn.style["opacity"] = "0.1"; |
|
} |
|
} |
|
]]> |
|
</script> |
|
<rect x="0" y="0" width="100%" height="100%" fill="rgb(240,240,220)"/> |
|
<text x="600" y="24" text-anchor="middle" style="font-size:17px">Flame Graph</text> |
|
<text x="10" y="245" id="details"> </text> |
|
<text x="10" y="24" id="unzoom" onclick="unzoom()" style="opacity:0.0;cursor:pointer">Reset Zoom</text> |
|
<text x="1090" y="24" id="search" onmouseover="searchover()" onmouseout="searchout()" onclick="search_prompt()" style="opacity:0.1;cursor:pointer">Search</text> |
|
<text x="1090" y="245" id="matched"> </text> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>all (10,225 samples, 100.00%)</title><rect x="10.0" y="211.0" width="1180.0" height="15" fill="#c83232" rx="2" ry="2"/> |
|
<text x="13.0" y="222.0">all</text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>[DestroyJavaVM tid=6403] (10,158 samples, 99.34%)</title><rect x="10.0" y="195.0" width="1172.3" height="15" fill="#cf3c3c" rx="2" ry="2"/> |
|
<text x="13.0" y="206.0">[DestroyJavaVM tid=6403]</text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>ProfileIdle.main (10,138 samples, 99.15%)</title><rect x="10.7" y="179.0" width="1170.0" height="15" fill="#5ff15f" rx="2" ry="2"/> |
|
<text x="13.7" y="190.0">ProfileIdle.main</text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>ProfileIdle.work (10,138 samples, 99.15%)</title><rect x="10.7" y="163.0" width="1170.0" height="15" fill="#4de14d" rx="2" ry="2"/> |
|
<text x="13.7" y="174.0">ProfileIdle.work</text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>java/lang/Math.atan (9,837 samples, 96.21%)</title><rect x="26.6" y="147.0" width="1135.2" height="15" fill="#51e551" rx="2" ry="2"/> |
|
<text x="29.6" y="158.0">java/lang/Math.atan</text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>java/lang/StrictMath.atan (9,793 samples, 95.78%)</title><rect x="31.7" y="131.0" width="1130.1" height="15" fill="#3fd43f" rx="2" ry="2"/> |
|
<text x="34.7" y="142.0">java/lang/StrictMath.atan</text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>Java_java_lang_StrictMath_atan (63 samples, 0.62%)</title><rect x="233.0" y="115.0" width="7.2" height="15" fill="#ca3535" rx="2" ry="2"/> |
|
<text x="236.0" y="126.0"></text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>jatan (7,923 samples, 77.49%)</title><rect x="240.2" y="115.0" width="914.4" height="15" fill="#ed6868" rx="2" ry="2"/> |
|
<text x="243.2" y="126.0">jatan</text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>jfabs (1,792 samples, 17.53%)</title><rect x="947.8" y="99.0" width="206.8" height="15" fill="#ed6868" rx="2" ry="2"/> |
|
<text x="950.8" y="110.0">jfabs</text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>jfabs (63 samples, 0.62%)</title><rect x="1154.6" y="115.0" width="7.2" height="15" fill="#fb7c7c" rx="2" ry="2"/> |
|
<text x="1157.6" y="126.0"></text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>java/lang/StrictMath.atan (163 samples, 1.59%)</title><rect x="1161.8" y="147.0" width="18.9" height="15" fill="#49dd49" rx="2" ry="2"/> |
|
<text x="1164.8" y="158.0"></text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>sun/launcher/LauncherHelper.checkAndLoadMain (10 samples, 0.10%)</title><rect x="1180.9" y="179.0" width="1.1" height="15" fill="#51e451" rx="2" ry="2"/> |
|
<text x="1183.9" y="190.0"></text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>java/lang/ClassLoader.loadClass (10 samples, 0.10%)</title><rect x="1180.9" y="163.0" width="1.1" height="15" fill="#63f563" rx="2" ry="2"/> |
|
<text x="1183.9" y="174.0"></text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>sun/misc/Launcher$AppClassLoader.loadClass (10 samples, 0.10%)</title><rect x="1180.9" y="147.0" width="1.1" height="15" fill="#34c934" rx="2" ry="2"/> |
|
<text x="1183.9" y="158.0"></text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>java/lang/ClassLoader.loadClass (10 samples, 0.10%)</title><rect x="1180.9" y="131.0" width="1.1" height="15" fill="#35ca35" rx="2" ry="2"/> |
|
<text x="1183.9" y="142.0"></text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>[tid=15875] (46 samples, 0.45%)</title><rect x="1183.4" y="195.0" width="5.3" height="15" fill="#e55c5c" rx="2" ry="2"/> |
|
<text x="1186.4" y="206.0"></text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>thread_start (46 samples, 0.45%)</title><rect x="1183.4" y="179.0" width="5.3" height="15" fill="#ec6767" rx="2" ry="2"/> |
|
<text x="1186.4" y="190.0"></text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>_pthread_start (46 samples, 0.45%)</title><rect x="1183.4" y="163.0" width="5.3" height="15" fill="#c83232" rx="2" ry="2"/> |
|
<text x="1186.4" y="174.0"></text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>_pthread_body (46 samples, 0.45%)</title><rect x="1183.4" y="147.0" width="5.3" height="15" fill="#dd5050" rx="2" ry="2"/> |
|
<text x="1186.4" y="158.0"></text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>java_start(Thread*) (46 samples, 0.45%)</title><rect x="1183.4" y="131.0" width="5.3" height="15" fill="#cb3737" rx="2" ry="2"/> |
|
<text x="1186.4" y="142.0"></text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>WatcherThread::run() (46 samples, 0.45%)</title><rect x="1183.4" y="115.0" width="5.3" height="15" fill="#c5c53a" rx="2" ry="2"/> |
|
<text x="1186.4" y="126.0"></text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>WatcherThread::sleep() const (44 samples, 0.43%)</title><rect x="1183.7" y="99.0" width="5.0" height="15" fill="#d4d43f" rx="2" ry="2"/> |
|
<text x="1186.7" y="110.0"></text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>Monitor::wait(bool, long, bool) (43 samples, 0.42%)</title><rect x="1183.7" y="83.0" width="4.9" height="15" fill="#cfcf3d" rx="2" ry="2"/> |
|
<text x="1186.7" y="94.0"></text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>Monitor::IWait(Thread*, long) (40 samples, 0.39%)</title><rect x="1183.7" y="67.0" width="4.6" height="15" fill="#e2e244" rx="2" ry="2"/> |
|
<text x="1186.7" y="78.0"></text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>os::PlatformEvent::park(long) (37 samples, 0.36%)</title><rect x="1183.9" y="51.0" width="4.3" height="15" fill="#dddd42" rx="2" ry="2"/> |
|
<text x="1186.9" y="62.0"></text> |
|
</g> |
|
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> |
|
<title>__psynch_cvwait (34 samples, 0.33%)</title><rect x="1184.1" y="35.0" width="3.9" height="15" fill="#e45c5c" rx="2" ry="2"/> |
|
<text x="1187.1" y="46.0"></text> |
|
</g> |
|
</svg> |