JezK
Edit File: phpspy_20261003_135401.svg
<?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="246" onload="init(evt)" viewBox="0 0 1200 246" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <!-- Flame graph stack visualization. See https://github.com/brendangregg/FlameGraph for latest version, and http://www.brendangregg.com/flamegraphs.html for examples. --> <!-- NOTES: --> <defs > <linearGradient id="background" y1="0" y2="1" x1="0" x2="0" > <stop stop-color="#eeeeee" offset="5%" /> <stop stop-color="#eeeeb0" offset="95%" /> </linearGradient> </defs> <style type="text/css"> .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.0" y="0" width="1200.0" height="246.0" fill="url(#background)" /> <text text-anchor="middle" x="600.00" y="24" font-size="17" font-family="Verdana" fill="rgb(0,0,0)" >Flame Graph</text> <text text-anchor="" x="10.00" y="229" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" id="details" > </text> <text text-anchor="" x="10.00" y="24" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" id="unzoom" onclick="unzoom()" style="opacity:0.0;cursor:pointer" >Reset Zoom</text> <text text-anchor="" x="1090.00" y="24" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" id="search" onmouseover="searchover()" onmouseout="searchout()" onclick="search_prompt()" style="opacity:0.1;cursor:pointer" >Search</text> <text text-anchor="" x="1090.00" y="229" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" id="matched" > </text> <g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> <title>get_home_url (1 samples, 20.00%)</title><rect x="954.0" y="181" width="236.0" height="15.0" fill="rgb(228,55,54)" rx="2" ry="2" /> <text text-anchor="" x="957.00" y="191.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >get_home_url</text> </g> <g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> <title><main> (2 samples, 40.00%)</title><rect x="10.0" y="165" width="472.0" height="15.0" fill="rgb(248,7,37)" rx="2" ry="2" /> <text text-anchor="" x="13.00" y="175.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ><main></text> </g> <g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> <title>all (5 samples, 100%)</title><rect x="10.0" y="197" width="1180.0" height="15.0" fill="rgb(215,177,9)" rx="2" ry="2" /> <text text-anchor="" x="13.00" y="207.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text> </g> <g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> <title>WP_Block_Type::set_props (1 samples, 20.00%)</title><rect x="482.0" y="181" width="236.0" height="15.0" fill="rgb(209,55,22)" rx="2" ry="2" /> <text text-anchor="" x="485.00" y="191.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >WP_Block_Type::set_props</text> </g> <g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> <title>wpdb::get_var (1 samples, 20.00%)</title><rect x="246.0" y="85" width="236.0" height="15.0" fill="rgb(244,168,43)" rx="2" ry="2" /> <text text-anchor="" x="249.00" y="95.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >wpdb::get_var</text> </g> <g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> <title>wp_load_alloptions (1 samples, 20.00%)</title><rect x="954.0" y="149" width="236.0" height="15.0" fill="rgb(253,217,48)" rx="2" ry="2" /> <text text-anchor="" x="957.00" y="159.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >wp_load_alloptions</text> </g> <g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> <title>is_ssl (1 samples, 20.00%)</title><rect x="954.0" y="165" width="236.0" height="15.0" fill="rgb(229,102,3)" rx="2" ry="2" /> <text text-anchor="" x="957.00" y="175.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >is_ssl</text> </g> <g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> <title>WP::send_headers (1 samples, 20.00%)</title><rect x="246.0" y="117" width="236.0" height="15.0" fill="rgb(241,225,42)" rx="2" ry="2" /> <text text-anchor="" x="249.00" y="127.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >WP::send_headers</text> </g> <g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> <title>mysqli_query (1 samples, 20.00%)</title><rect x="246.0" y="37" width="236.0" height="15.0" fill="rgb(211,173,2)" rx="2" ry="2" /> <text text-anchor="" x="249.00" y="47.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >mysqli_query</text> </g> <g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> <title>wpdb::_do_query (1 samples, 20.00%)</title><rect x="246.0" y="53" width="236.0" height="15.0" fill="rgb(247,172,18)" rx="2" ry="2" /> <text text-anchor="" x="249.00" y="63.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >wpdb::_do_query</text> </g> <g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> <title>get_lastcommentmodified (1 samples, 20.00%)</title><rect x="246.0" y="101" width="236.0" height="15.0" fill="rgb(220,30,28)" rx="2" ry="2" /> <text text-anchor="" x="249.00" y="111.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >get_lastcommentmodified</text> </g> <g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> <title><main> (2 samples, 40.00%)</title><rect x="10.0" y="181" width="472.0" height="15.0" fill="rgb(232,12,40)" rx="2" ry="2" /> <text text-anchor="" x="13.00" y="191.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ><main></text> </g> <g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> <title>wp (2 samples, 40.00%)</title><rect x="10.0" y="149" width="472.0" height="15.0" fill="rgb(252,148,6)" rx="2" ry="2" /> <text text-anchor="" x="13.00" y="159.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >wp</text> </g> <g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> <title>WP::parse_request (1 samples, 20.00%)</title><rect x="10.0" y="117" width="236.0" height="15.0" fill="rgb(238,27,31)" rx="2" ry="2" /> <text text-anchor="" x="13.00" y="127.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >WP::parse_request</text> </g> <g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> <title>wpdb::query (1 samples, 20.00%)</title><rect x="246.0" y="69" width="236.0" height="15.0" fill="rgb(253,129,37)" rx="2" ry="2" /> <text text-anchor="" x="249.00" y="79.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >wpdb::query</text> </g> <g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> <title>preg_match (1 samples, 20.00%)</title><rect x="10.0" y="101" width="236.0" height="15.0" fill="rgb(223,114,50)" rx="2" ry="2" /> <text text-anchor="" x="13.00" y="111.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >preg_match</text> </g> <g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> <title>aviaShortcodeTemplate::__destruct (1 samples, 20.00%)</title><rect x="718.0" y="181" width="236.0" height="15.0" fill="rgb(249,151,15)" rx="2" ry="2" /> <text text-anchor="" x="721.00" y="191.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >aviaShortcodeTemplate::__destruct</text> </g> <g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"> <title>WP::main (2 samples, 40.00%)</title><rect x="10.0" y="133" width="472.0" height="15.0" fill="rgb(211,168,21)" rx="2" ry="2" /> <text text-anchor="" x="13.00" y="143.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >WP::main</text> </g> </svg>