Created
September 7, 2024 12:09
-
-
Save antocuni/aac6bc866c9e46f2a423b9f1e58ca796 to your computer and use it in GitHub Desktop.
scalene flamegraph
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?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="1800" height="242" onload="init(evt)" viewBox="0 0 1800 242" 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. --> | |
| <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, svg; | |
| function init(evt) { | |
| details = document.getElementById("details").firstChild; | |
| svg = document.getElementsByTagName("svg")[0]; | |
| searching = 0; | |
| } | |
| // mouse-over for info | |
| function s(info) { details.nodeValue = "Function: " + info; } | |
| function c() { details.nodeValue = ' '; } | |
| // 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 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; | |
| var searchbtn = document.getElementById("search"); | |
| searchbtn.style["opacity"] = "0.1"; | |
| searchbtn.firstChild.nodeValue = "Search" | |
| } | |
| } | |
| function search(term) { | |
| var re = new RegExp(term); | |
| var el = document.getElementsByTagName("g"); | |
| for (var i=0; i < el.length; i++){ | |
| var e = el[i]; | |
| if (e.attributes["class"].value == "func_g") { | |
| // Scrape the function name from the onmouseover | |
| // callback text. This is a little dirty. | |
| var func = e.attributes["onmouseover"].value; | |
| if (func != null) { | |
| func = func.substr(3); | |
| func = func.replace(/ .*/, ""); | |
| var r = find_child(e, "rect"); | |
| } | |
| if (func != null && r != null && | |
| func.match(re)) { | |
| orig_save(r, "fill"); | |
| r.attributes["fill"].value = | |
| "rgb(230,0,230)"; | |
| searching = 1; | |
| } | |
| } | |
| } | |
| if (searching) { | |
| var searchbtn = document.getElementById("search"); | |
| searchbtn.style["opacity"] = "1.0"; | |
| searchbtn.firstChild.nodeValue = "Reset Search" | |
| } | |
| } | |
| function searchover(e) { | |
| var searchbtn = document.getElementById("search"); | |
| searchbtn.style["opacity"] = "1.0"; | |
| } | |
| function searchout(e) { | |
| var searchbtn = document.getElementById("search"); | |
| if (searching) { | |
| searchbtn.style["opacity"] = "1.0"; | |
| } else { | |
| searchbtn.style["opacity"] = "0.1"; | |
| } | |
| } | |
| ]]> | |
| </script> | |
| <rect x="0.0" y="0" width="1800.0" height="242.0" fill="url(#background)" /> | |
| <text text-anchor="middle" x="900.00" y="24" font-size="17" font-family="Verdana" fill="rgb(0,0,0)" >Flame Graph</text> | |
| <text text-anchor="" x="10.00" y="225" 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="1690.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> | |
| <g class="func_g" onmouseover="s('Packet.append_to:/tmp/richards.py (1 samples, 0.21%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>Packet.append_to:/tmp/richards.py (1 samples, 0.21%)</title><rect x="1118.3" y="49" width="3.7" height="15.0" fill="rgb(234,69,26)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1121.30" y="59.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text> | |
| </g> | |
| <g class="func_g" onmouseover="s('Task.qpkt:/tmp/richards.py (36 samples, 7.55%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>Task.qpkt:/tmp/richards.py (36 samples, 7.55%)</title><rect x="1122.0" y="65" width="134.4" height="15.0" fill="rgb(210,213,31)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1125.03" y="75.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >Task.qpkt:/tmp/r..</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('DeviceTask.fn:/tmp/richards.py (58 samples, 12.16%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>DeviceTask.fn:/tmp/richards.py (58 samples, 12.16%)</title><rect x="786.2" y="81" width="216.4" height="15.0" fill="rgb(235,164,48)" rx="2" ry="2" /> | |
| <text text-anchor="" x="789.18" y="91.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >DeviceTask.fn:/tmp/richards.py</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('HandlerTaskRec.deviceInAdd:/tmp/richards.py (8 samples, 1.68%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>HandlerTaskRec.deviceInAdd:/tmp/richards.py (8 samples, 1.68%)</title><rect x="1073.5" y="65" width="29.9" height="15.0" fill="rgb(249,130,17)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1076.52" y="75.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >Ha..</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('Task.qpkt:/tmp/richards.py (5 samples, 1.05%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>Task.qpkt:/tmp/richards.py (5 samples, 1.05%)</title><rect x="1674.3" y="65" width="18.7" height="15.0" fill="rgb(220,138,28)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1677.32" y="75.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text> | |
| </g> | |
| <g class="func_g" onmouseover="s('Task.addPacket:/tmp/richards.py (18 samples, 3.77%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>Task.addPacket:/tmp/richards.py (18 samples, 3.77%)</title><rect x="1181.7" y="49" width="67.2" height="15.0" fill="rgb(243,189,28)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1184.74" y="59.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >Task.ad..</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('HandlerTaskRec.workInAdd:/tmp/richards.py (5 samples, 1.05%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>HandlerTaskRec.workInAdd:/tmp/richards.py (5 samples, 1.05%)</title><rect x="1103.4" y="65" width="18.6" height="15.0" fill="rgb(213,216,52)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1106.38" y="75.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text> | |
| </g> | |
| <g class="func_g" onmouseover="s('TaskState.packetPending:/tmp/richards.py (14 samples, 2.94%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>TaskState.packetPending:/tmp/richards.py (14 samples, 2.94%)</title><rect x="1457.9" y="81" width="52.2" height="15.0" fill="rgb(212,129,12)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1460.88" y="91.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >TaskS..</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('TaskState.running:/tmp/richards.py (27 samples, 5.66%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>TaskState.running:/tmp/richards.py (27 samples, 5.66%)</title><rect x="1510.1" y="81" width="100.8" height="15.0" fill="rgb(254,179,53)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1513.13" y="91.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >TaskState.ru..</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('Task.findtcb:/tmp/richards.py (4 samples, 0.84%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>Task.findtcb:/tmp/richards.py (4 samples, 0.84%)</title><rect x="972.8" y="49" width="14.9" height="15.0" fill="rgb(208,78,24)" rx="2" ry="2" /> | |
| <text text-anchor="" x="975.77" y="59.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text> | |
| </g> | |
| <g class="func_g" onmouseover="s('Task.qpkt:/tmp/richards.py (18 samples, 3.77%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>Task.qpkt:/tmp/richards.py (18 samples, 3.77%)</title><rect x="920.5" y="65" width="67.2" height="15.0" fill="rgb(210,31,48)" rx="2" ry="2" /> | |
| <text text-anchor="" x="923.52" y="75.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >Task.qp..</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('Task.hold:/tmp/richards.py (4 samples, 0.84%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>Task.hold:/tmp/richards.py (4 samples, 0.84%)</title><rect x="905.6" y="65" width="14.9" height="15.0" fill="rgb(242,42,54)" rx="2" ry="2" /> | |
| <text text-anchor="" x="908.60" y="75.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text> | |
| </g> | |
| <g class="func_g" onmouseover="s('all (477 samples, 100%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>all (477 samples, 100%)</title><rect x="10.0" y="193" width="1780.0" height="15.0" fill="rgb(246,163,1)" rx="2" ry="2" /> | |
| <text text-anchor="" x="13.00" y="203.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text> | |
| </g> | |
| <g class="func_g" onmouseover="s('main:/tmp/richards.py (477 samples, 100.00%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>main:/tmp/richards.py (477 samples, 100.00%)</title><rect x="10.0" y="161" width="1780.0" height="15.0" fill="rgb(242,129,21)" rx="2" ry="2" /> | |
| <text text-anchor="" x="13.00" y="171.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >main:/tmp/richards.py</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('Richards.run:/tmp/richards.py (477 samples, 100.00%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>Richards.run:/tmp/richards.py (477 samples, 100.00%)</title><rect x="10.0" y="129" width="1780.0" height="15.0" fill="rgb(206,41,42)" rx="2" ry="2" /> | |
| <text text-anchor="" x="13.00" y="139.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >Richards.run:/tmp/richards.py</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('schedule:/tmp/richards.py (477 samples, 100.00%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>schedule:/tmp/richards.py (477 samples, 100.00%)</title><rect x="10.0" y="113" width="1780.0" height="15.0" fill="rgb(240,22,23)" rx="2" ry="2" /> | |
| <text text-anchor="" x="13.00" y="123.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >schedule:/tmp/richards.py</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('Task.runTask:/tmp/richards.py (318 samples, 66.67%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>Task.runTask:/tmp/richards.py (318 samples, 66.67%)</title><rect x="510.0" y="97" width="1186.7" height="15.0" fill="rgb(209,94,52)" rx="2" ry="2" /> | |
| <text text-anchor="" x="513.04" y="107.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >Task.runTask:/tmp/richards.py</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('Task.findtcb:/tmp/richards.py (2 samples, 0.42%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>Task.findtcb:/tmp/richards.py (2 samples, 0.42%)</title><rect x="1685.5" y="49" width="7.5" height="15.0" fill="rgb(219,162,14)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1688.51" y="59.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text> | |
| </g> | |
| <g class="func_g" onmouseover="s('(module):/tmp/richards.py (477 samples, 100.00%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>(module):/tmp/richards.py (477 samples, 100.00%)</title><rect x="10.0" y="177" width="1780.0" height="15.0" fill="rgb(253,172,15)" rx="2" ry="2" /> | |
| <text text-anchor="" x="13.00" y="187.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >(module):/tmp/richards.py</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('Task.addPacket:/tmp/richards.py (1 samples, 0.21%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>Task.addPacket:/tmp/richards.py (1 samples, 0.21%)</title><rect x="1681.8" y="49" width="3.7" height="15.0" fill="rgb(244,2,50)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1684.78" y="59.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text> | |
| </g> | |
| <g class="func_g" onmouseover="s('TaskState.isWaitingWithPacket:/tmp/richards.py (15 samples, 3.14%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>TaskState.isWaitingWithPacket:/tmp/richards.py (15 samples, 3.14%)</title><rect x="1401.9" y="81" width="56.0" height="15.0" fill="rgb(243,188,21)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1404.91" y="91.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >TaskS..</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('Packet.append_to:/tmp/richards.py (2 samples, 0.42%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>Packet.append_to:/tmp/richards.py (2 samples, 0.42%)</title><rect x="1095.9" y="49" width="7.5" height="15.0" fill="rgb(254,49,27)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1098.91" y="59.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text> | |
| </g> | |
| <g class="func_g" onmouseover="s('IdleTask.fn:/tmp/richards.py (31 samples, 6.50%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>IdleTask.fn:/tmp/richards.py (31 samples, 6.50%)</title><rect x="1286.2" y="81" width="115.7" height="15.0" fill="rgb(221,16,19)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1289.23" y="91.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >IdleTask.fn:/t..</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('Task.findtcb:/tmp/richards.py (3 samples, 0.63%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>Task.findtcb:/tmp/richards.py (3 samples, 0.63%)</title><rect x="1390.7" y="49" width="11.2" height="15.0" fill="rgb(243,36,0)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1393.71" y="59.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text> | |
| </g> | |
| <g class="func_g" onmouseover="s('HandlerTask.fn:/tmp/richards.py (76 samples, 15.93%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>HandlerTask.fn:/tmp/richards.py (76 samples, 15.93%)</title><rect x="1002.6" y="81" width="283.6" height="15.0" fill="rgb(236,187,30)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1005.62" y="91.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >HandlerTask.fn:/tmp/richards.py</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('entry_point:/tmp/richards.py (477 samples, 100.00%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>entry_point:/tmp/richards.py (477 samples, 100.00%)</title><rect x="10.0" y="145" width="1780.0" height="15.0" fill="rgb(217,224,32)" rx="2" ry="2" /> | |
| <text text-anchor="" x="13.00" y="155.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >entry_point:/tmp/richards.py</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('Task.waitTask:/tmp/richards.py (4 samples, 0.84%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>Task.waitTask:/tmp/richards.py (4 samples, 0.84%)</title><rect x="987.7" y="65" width="14.9" height="15.0" fill="rgb(221,100,42)" rx="2" ry="2" /> | |
| <text text-anchor="" x="990.69" y="75.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text> | |
| </g> | |
| <g class="func_g" onmouseover="s('Task.findtcb:/tmp/richards.py (2 samples, 0.42%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>Task.findtcb:/tmp/richards.py (2 samples, 0.42%)</title><rect x="1248.9" y="49" width="7.5" height="15.0" fill="rgb(214,80,23)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1251.91" y="59.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text> | |
| </g> | |
| <g class="func_g" onmouseover="s('Task.waitTask:/tmp/richards.py (1 samples, 0.21%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>Task.waitTask:/tmp/richards.py (1 samples, 0.21%)</title><rect x="1693.0" y="65" width="3.7" height="15.0" fill="rgb(229,27,45)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1695.98" y="75.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text> | |
| </g> | |
| <g class="func_g" onmouseover="s('Task.release:/tmp/richards.py (25 samples, 5.24%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>Task.release:/tmp/richards.py (25 samples, 5.24%)</title><rect x="1308.6" y="65" width="93.3" height="15.0" fill="rgb(251,20,12)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1311.62" y="75.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >Task.releas..</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('WorkTask.fn:/tmp/richards.py (23 samples, 4.82%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>WorkTask.fn:/tmp/richards.py (23 samples, 4.82%)</title><rect x="1610.9" y="81" width="85.8" height="15.0" fill="rgb(223,13,41)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1613.88" y="91.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >WorkTask.f..</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('Task.addPacket:/tmp/richards.py (9 samples, 1.89%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>Task.addPacket:/tmp/richards.py (9 samples, 1.89%)</title><rect x="939.2" y="49" width="33.6" height="15.0" fill="rgb(216,41,36)" rx="2" ry="2" /> | |
| <text text-anchor="" x="942.18" y="59.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >Ta..</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('Task.waitTask:/tmp/richards.py (8 samples, 1.68%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>Task.waitTask:/tmp/richards.py (8 samples, 1.68%)</title><rect x="1256.4" y="65" width="29.8" height="15.0" fill="rgb(228,2,17)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1259.37" y="75.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >Ta..</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('TaskState.isTaskHoldingOrWaiting:/tmp/richards.py (25 samples, 5.24%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>TaskState.isTaskHoldingOrWaiting:/tmp/richards.py (25 samples, 5.24%)</title><rect x="1696.7" y="97" width="93.3" height="15.0" fill="rgb(214,86,14)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1699.71" y="107.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >TaskState.i..</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('Packet.append_to:/tmp/richards.py (2 samples, 0.42%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>Packet.append_to:/tmp/richards.py (2 samples, 0.42%)</title><rect x="1241.4" y="33" width="7.5" height="15.0" fill="rgb(236,100,34)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1244.45" y="43.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text> | |
| </g> | |
| </svg> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?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="1800" height="242" onload="init(evt)" viewBox="0 0 1800 242" 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. --> | |
| <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, svg; | |
| function init(evt) { | |
| details = document.getElementById("details").firstChild; | |
| svg = document.getElementsByTagName("svg")[0]; | |
| searching = 0; | |
| } | |
| // mouse-over for info | |
| function s(info) { details.nodeValue = "Function: " + info; } | |
| function c() { details.nodeValue = ' '; } | |
| // 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 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; | |
| var searchbtn = document.getElementById("search"); | |
| searchbtn.style["opacity"] = "0.1"; | |
| searchbtn.firstChild.nodeValue = "Search" | |
| } | |
| } | |
| function search(term) { | |
| var re = new RegExp(term); | |
| var el = document.getElementsByTagName("g"); | |
| for (var i=0; i < el.length; i++){ | |
| var e = el[i]; | |
| if (e.attributes["class"].value == "func_g") { | |
| // Scrape the function name from the onmouseover | |
| // callback text. This is a little dirty. | |
| var func = e.attributes["onmouseover"].value; | |
| if (func != null) { | |
| func = func.substr(3); | |
| func = func.replace(/ .*/, ""); | |
| var r = find_child(e, "rect"); | |
| } | |
| if (func != null && r != null && | |
| func.match(re)) { | |
| orig_save(r, "fill"); | |
| r.attributes["fill"].value = | |
| "rgb(230,0,230)"; | |
| searching = 1; | |
| } | |
| } | |
| } | |
| if (searching) { | |
| var searchbtn = document.getElementById("search"); | |
| searchbtn.style["opacity"] = "1.0"; | |
| searchbtn.firstChild.nodeValue = "Reset Search" | |
| } | |
| } | |
| function searchover(e) { | |
| var searchbtn = document.getElementById("search"); | |
| searchbtn.style["opacity"] = "1.0"; | |
| } | |
| function searchout(e) { | |
| var searchbtn = document.getElementById("search"); | |
| if (searching) { | |
| searchbtn.style["opacity"] = "1.0"; | |
| } else { | |
| searchbtn.style["opacity"] = "0.1"; | |
| } | |
| } | |
| ]]> | |
| </script> | |
| <rect x="0.0" y="0" width="1800.0" height="242.0" fill="url(#background)" /> | |
| <text text-anchor="middle" x="900.00" y="24" font-size="17" font-family="Verdana" fill="rgb(0,0,0)" >Flame Graph</text> | |
| <text text-anchor="" x="10.00" y="225" 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="1690.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> | |
| <g class="func_g" onmouseover="s('(module):/tmp/richards.py (469 samples, 100.00%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>(module):/tmp/richards.py (469 samples, 100.00%)</title><rect x="10.0" y="177" width="1780.0" height="15.0" fill="rgb(252,117,1)" rx="2" ry="2" /> | |
| <text text-anchor="" x="13.00" y="187.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >(module):/tmp/richards.py</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('append_to:/tmp/richards.py (3 samples, 0.64%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>append_to:/tmp/richards.py (3 samples, 0.64%)</title><rect x="1114.4" y="49" width="11.4" height="15.0" fill="rgb(222,186,47)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1117.43" y="59.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text> | |
| </g> | |
| <g class="func_g" onmouseover="s('waitTask:/tmp/richards.py (10 samples, 2.13%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>waitTask:/tmp/richards.py (10 samples, 2.13%)</title><rect x="1531.9" y="65" width="38.0" height="15.0" fill="rgb(238,135,36)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1534.92" y="75.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >wai..</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('schedule:/tmp/richards.py (469 samples, 100.00%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>schedule:/tmp/richards.py (469 samples, 100.00%)</title><rect x="10.0" y="113" width="1780.0" height="15.0" fill="rgb(211,17,2)" rx="2" ry="2" /> | |
| <text text-anchor="" x="13.00" y="123.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >schedule:/tmp/richards.py</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('findtcb:/tmp/richards.py (9 samples, 1.92%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>findtcb:/tmp/richards.py (9 samples, 1.92%)</title><rect x="1391.5" y="49" width="34.2" height="15.0" fill="rgb(249,77,32)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1394.49" y="59.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >fi..</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('packetPending:/tmp/richards.py (13 samples, 2.77%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>packetPending:/tmp/richards.py (13 samples, 2.77%)</title><rect x="1630.6" y="81" width="49.3" height="15.0" fill="rgb(234,61,20)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1633.60" y="91.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >pack..</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('release:/tmp/richards.py (28 samples, 5.97%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>release:/tmp/richards.py (28 samples, 5.97%)</title><rect x="1425.7" y="65" width="106.2" height="15.0" fill="rgb(208,168,43)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1428.65" y="75.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >release:/tmp/..</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('isTaskHoldingOrWaiting:/tmp/richards.py (33 samples, 7.04%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>isTaskHoldingOrWaiting:/tmp/richards.py (33 samples, 7.04%)</title><rect x="488.2" y="97" width="125.3" height="15.0" fill="rgb(211,196,39)" rx="2" ry="2" /> | |
| <text text-anchor="" x="491.21" y="107.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >isTaskHoldingOr..</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('main:/tmp/richards.py (469 samples, 100.00%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>main:/tmp/richards.py (469 samples, 100.00%)</title><rect x="10.0" y="161" width="1780.0" height="15.0" fill="rgb(232,81,6)" rx="2" ry="2" /> | |
| <text text-anchor="" x="13.00" y="171.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >main:/tmp/richards.py</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('run:/tmp/richards.py (469 samples, 100.00%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>run:/tmp/richards.py (469 samples, 100.00%)</title><rect x="10.0" y="129" width="1780.0" height="15.0" fill="rgb(228,85,48)" rx="2" ry="2" /> | |
| <text text-anchor="" x="13.00" y="139.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >run:/tmp/richards.py</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('workInAdd:/tmp/richards.py (3 samples, 0.64%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>workInAdd:/tmp/richards.py (3 samples, 0.64%)</title><rect x="1569.9" y="65" width="11.4" height="15.0" fill="rgb(238,28,21)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1572.87" y="75.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text> | |
| </g> | |
| <g class="func_g" onmouseover="s('deviceInAdd:/tmp/richards.py (11 samples, 2.35%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>deviceInAdd:/tmp/richards.py (11 samples, 2.35%)</title><rect x="1084.1" y="65" width="41.7" height="15.0" fill="rgb(214,85,21)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1087.07" y="75.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >dev..</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('hold:/tmp/richards.py (6 samples, 1.28%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>hold:/tmp/richards.py (6 samples, 1.28%)</title><rect x="1125.8" y="65" width="22.8" height="15.0" fill="rgb(223,172,48)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1128.82" y="75.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >h..</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('runTask:/tmp/richards.py (310 samples, 66.10%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>runTask:/tmp/richards.py (310 samples, 66.10%)</title><rect x="613.5" y="97" width="1176.5" height="15.0" fill="rgb(237,135,24)" rx="2" ry="2" /> | |
| <text text-anchor="" x="616.45" y="107.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >runTask:/tmp/richards.py</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('findtcb:/tmp/richards.py (1 samples, 0.21%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>findtcb:/tmp/richards.py (1 samples, 0.21%)</title><rect x="1528.1" y="49" width="3.8" height="15.0" fill="rgb(221,174,11)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1531.12" y="59.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text> | |
| </g> | |
| <g class="func_g" onmouseover="s('qpkt:/tmp/richards.py (73 samples, 15.57%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>qpkt:/tmp/richards.py (73 samples, 15.57%)</title><rect x="1148.6" y="65" width="277.1" height="15.0" fill="rgb(213,9,6)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1151.59" y="75.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >qpkt:/tmp/richards.py</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('running:/tmp/richards.py (29 samples, 6.18%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>running:/tmp/richards.py (29 samples, 6.18%)</title><rect x="1679.9" y="81" width="110.1" height="15.0" fill="rgb(211,207,46)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1682.94" y="91.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >running:/tmp/..</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('all (469 samples, 100%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>all (469 samples, 100%)</title><rect x="10.0" y="193" width="1780.0" height="15.0" fill="rgb(249,103,48)" rx="2" ry="2" /> | |
| <text text-anchor="" x="13.00" y="203.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text> | |
| </g> | |
| <g class="func_g" onmouseover="s('fn:/tmp/richards.py (196 samples, 41.79%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>fn:/tmp/richards.py (196 samples, 41.79%)</title><rect x="837.4" y="81" width="743.9" height="15.0" fill="rgb(251,36,51)" rx="2" ry="2" /> | |
| <text text-anchor="" x="840.38" y="91.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >fn:/tmp/richards.py</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('isWaitingWithPacket:/tmp/richards.py (13 samples, 2.77%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>isWaitingWithPacket:/tmp/richards.py (13 samples, 2.77%)</title><rect x="1581.3" y="81" width="49.3" height="15.0" fill="rgb(239,128,48)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1584.26" y="91.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >isWa..</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('addPacket:/tmp/richards.py (45 samples, 9.59%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>addPacket:/tmp/richards.py (45 samples, 9.59%)</title><rect x="1220.7" y="49" width="170.8" height="15.0" fill="rgb(246,221,25)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1223.70" y="59.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >addPacket:/tmp/richard..</text> | |
| </g> | |
| <g class="func_g" onmouseover="s('append_to:/tmp/richards.py (5 samples, 1.07%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>append_to:/tmp/richards.py (5 samples, 1.07%)</title><rect x="1372.5" y="33" width="19.0" height="15.0" fill="rgb(227,152,5)" rx="2" ry="2" /> | |
| <text text-anchor="" x="1375.52" y="43.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text> | |
| </g> | |
| <g class="func_g" onmouseover="s('entry_point:/tmp/richards.py (469 samples, 100.00%)')" onmouseout="c()" onclick="zoom(this)"> | |
| <title>entry_point:/tmp/richards.py (469 samples, 100.00%)</title><rect x="10.0" y="145" width="1780.0" height="15.0" fill="rgb(252,136,7)" rx="2" ry="2" /> | |
| <text text-anchor="" x="13.00" y="155.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >entry_point:/tmp/richards.py</text> | |
| </g> | |
| </svg> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| To create a flamegraph: | |
| $ python -m scalene --json --no-browser --stacks --cpu-sampling-rate 0.001 richards.py | |
| $ python foldstack.py profile.json | /tmp/FlameGraph/flamegraph.pl > flamegraph.html | |
| """ | |
| import sys | |
| import json | |
| def main(): | |
| fname = sys.argv[1] | |
| with open(fname) as f: | |
| data = json.load(f) | |
| for frames, stats in data['stacks']: | |
| count, py_time, c_time, cpu_samples = stats | |
| lines = [f'{fn}:{filename}' for filename, fn, lineno in frames] | |
| folded = ';'.join(lines) | |
| print(f'{folded} {count}') | |
| if __name__ == '__main__': | |
| main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| based on a Java version: | |
| Based on original version written in BCPL by Dr Martin Richards | |
| in 1981 at Cambridge University Computer Laboratory, England | |
| and a C++ version derived from a Smalltalk version written by | |
| L Peter Deutsch. | |
| Java version: Copyright (C) 1995 Sun Microsystems, Inc. | |
| Translation from C++, Mario Wolczko | |
| Outer loop added by Alex Jacoby | |
| """ | |
| import time | |
| # Task IDs | |
| I_IDLE = 1 | |
| I_WORK = 2 | |
| I_HANDLERA = 3 | |
| I_HANDLERB = 4 | |
| I_DEVA = 5 | |
| I_DEVB = 6 | |
| # Packet types | |
| K_DEV = 1000 | |
| K_WORK = 1001 | |
| # Packet | |
| BUFSIZE = 4 | |
| BUFSIZE_RANGE = range(BUFSIZE) | |
| class Packet(object): | |
| def __init__(self, l, i, k): | |
| self.link = l | |
| self.ident = i | |
| self.kind = k | |
| self.datum = 0 | |
| self.data = [0] * BUFSIZE | |
| def append_to(self, lst): | |
| self.link = None | |
| if lst is None: | |
| return self | |
| else: | |
| p = lst | |
| next = p.link | |
| while next is not None: | |
| p = next | |
| next = p.link | |
| p.link = self | |
| return lst | |
| # Task Records | |
| class TaskRec(object): | |
| pass | |
| class DeviceTaskRec(TaskRec): | |
| def __init__(self): | |
| self.pending = None | |
| class IdleTaskRec(TaskRec): | |
| def __init__(self): | |
| self.control = 1 | |
| self.count = 10000 | |
| class HandlerTaskRec(TaskRec): | |
| def __init__(self): | |
| self.work_in = None | |
| self.device_in = None | |
| def workInAdd(self, p): | |
| self.work_in = p.append_to(self.work_in) | |
| return self.work_in | |
| def deviceInAdd(self, p): | |
| self.device_in = p.append_to(self.device_in) | |
| return self.device_in | |
| class WorkerTaskRec(TaskRec): | |
| def __init__(self): | |
| self.destination = I_HANDLERA | |
| self.count = 0 | |
| # Task | |
| class TaskState(object): | |
| def __init__(self): | |
| self.packet_pending = True | |
| self.task_waiting = False | |
| self.task_holding = False | |
| def packetPending(self): | |
| self.packet_pending = True | |
| self.task_waiting = False | |
| self.task_holding = False | |
| return self | |
| def waiting(self): | |
| self.packet_pending = False | |
| self.task_waiting = True | |
| self.task_holding = False | |
| return self | |
| def running(self): | |
| self.packet_pending = False | |
| self.task_waiting = False | |
| self.task_holding = False | |
| return self | |
| def waitingWithPacket(self): | |
| self.packet_pending = True | |
| self.task_waiting = True | |
| self.task_holding = False | |
| return self | |
| def isPacketPending(self): | |
| return self.packet_pending | |
| def isTaskWaiting(self): | |
| return self.task_waiting | |
| def isTaskHolding(self): | |
| return self.task_holding | |
| def isTaskHoldingOrWaiting(self): | |
| return self.task_holding or (not self.packet_pending and self.task_waiting) | |
| def isWaitingWithPacket(self): | |
| return self.packet_pending and self.task_waiting and not self.task_holding | |
| tracing = False | |
| layout = 0 | |
| def trace(a): | |
| global layout | |
| layout -= 1 | |
| if layout <= 0: | |
| print() | |
| layout = 50 | |
| print(a, end='') | |
| TASKTABSIZE = 10 | |
| class TaskWorkArea(object): | |
| def __init__(self): | |
| self.taskTab = [None] * TASKTABSIZE | |
| self.taskList = None | |
| self.holdCount = 0 | |
| self.qpktCount = 0 | |
| taskWorkArea = TaskWorkArea() | |
| class Task(TaskState): | |
| def __init__(self, i, p, w, initialState, r): | |
| self.link = taskWorkArea.taskList | |
| self.ident = i | |
| self.priority = p | |
| self.input = w | |
| self.packet_pending = initialState.isPacketPending() | |
| self.task_waiting = initialState.isTaskWaiting() | |
| self.task_holding = initialState.isTaskHolding() | |
| self.handle = r | |
| taskWorkArea.taskList = self | |
| taskWorkArea.taskTab[i] = self | |
| def fn(self, pkt, r): | |
| raise NotImplementedError | |
| def addPacket(self, p, old): | |
| if self.input is None: | |
| self.input = p | |
| self.packet_pending = True | |
| if self.priority > old.priority: | |
| return self | |
| else: | |
| p.append_to(self.input) | |
| return old | |
| def runTask(self): | |
| if self.isWaitingWithPacket(): | |
| msg = self.input | |
| self.input = msg.link | |
| if self.input is None: | |
| self.running() | |
| else: | |
| self.packetPending() | |
| else: | |
| msg = None | |
| return self.fn(msg, self.handle) | |
| def waitTask(self): | |
| self.task_waiting = True | |
| return self | |
| def hold(self): | |
| taskWorkArea.holdCount += 1 | |
| self.task_holding = True | |
| return self.link | |
| def release(self, i): | |
| t = self.findtcb(i) | |
| t.task_holding = False | |
| if t.priority > self.priority: | |
| return t | |
| else: | |
| return self | |
| def qpkt(self, pkt): | |
| t = self.findtcb(pkt.ident) | |
| taskWorkArea.qpktCount += 1 | |
| pkt.link = None | |
| pkt.ident = self.ident | |
| return t.addPacket(pkt, self) | |
| def findtcb(self, id): | |
| t = taskWorkArea.taskTab[id] | |
| if t is None: | |
| raise Exception("Bad task id %d" % id) | |
| return t | |
| # DeviceTask | |
| class DeviceTask(Task): | |
| def __init__(self, i, p, w, s, r): | |
| Task.__init__(self, i, p, w, s, r) | |
| def fn(self, pkt, r): | |
| d = r | |
| assert isinstance(d, DeviceTaskRec) | |
| if pkt is None: | |
| pkt = d.pending | |
| if pkt is None: | |
| return self.waitTask() | |
| else: | |
| d.pending = None | |
| return self.qpkt(pkt) | |
| else: | |
| d.pending = pkt | |
| if tracing: | |
| trace(pkt.datum) | |
| return self.hold() | |
| class HandlerTask(Task): | |
| def __init__(self, i, p, w, s, r): | |
| Task.__init__(self, i, p, w, s, r) | |
| def fn(self, pkt, r): | |
| h = r | |
| assert isinstance(h, HandlerTaskRec) | |
| if pkt is not None: | |
| if pkt.kind == K_WORK: | |
| h.workInAdd(pkt) | |
| else: | |
| h.deviceInAdd(pkt) | |
| work = h.work_in | |
| if work is None: | |
| return self.waitTask() | |
| count = work.datum | |
| if count >= BUFSIZE: | |
| h.work_in = work.link | |
| return self.qpkt(work) | |
| dev = h.device_in | |
| if dev is None: | |
| return self.waitTask() | |
| h.device_in = dev.link | |
| dev.datum = work.data[count] | |
| work.datum = count + 1 | |
| return self.qpkt(dev) | |
| # IdleTask | |
| class IdleTask(Task): | |
| def __init__(self, i, p, w, s, r): | |
| Task.__init__(self, i, 0, None, s, r) | |
| def fn(self, pkt, r): | |
| i = r | |
| assert isinstance(i, IdleTaskRec) | |
| i.count -= 1 | |
| if i.count == 0: | |
| return self.hold() | |
| elif i.control & 1 == 0: | |
| i.control //= 2 | |
| return self.release(I_DEVA) | |
| else: | |
| i.control = i.control // 2 ^ 0xd008 | |
| return self.release(I_DEVB) | |
| # WorkTask | |
| A = ord('A') | |
| class WorkTask(Task): | |
| def __init__(self, i, p, w, s, r): | |
| Task.__init__(self, i, p, w, s, r) | |
| def fn(self, pkt, r): | |
| w = r | |
| assert isinstance(w, WorkerTaskRec) | |
| if pkt is None: | |
| return self.waitTask() | |
| if w.destination == I_HANDLERA: | |
| dest = I_HANDLERB | |
| else: | |
| dest = I_HANDLERA | |
| w.destination = dest | |
| pkt.ident = dest | |
| pkt.datum = 0 | |
| for i in BUFSIZE_RANGE: # range(BUFSIZE) | |
| w.count += 1 | |
| if w.count > 26: | |
| w.count = 1 | |
| pkt.data[i] = A + w.count - 1 | |
| return self.qpkt(pkt) | |
| def schedule(): | |
| t = taskWorkArea.taskList | |
| while t is not None: | |
| if tracing: | |
| print("tcb =", t.ident) | |
| if t.isTaskHoldingOrWaiting(): | |
| t = t.link | |
| else: | |
| if tracing: | |
| trace(chr(ord("0") + t.ident)) | |
| t = t.runTask() | |
| class Richards(object): | |
| def run(self, iterations): | |
| for i in range(iterations): | |
| taskWorkArea.holdCount = 0 | |
| taskWorkArea.qpktCount = 0 | |
| IdleTask(I_IDLE, 1, 10000, TaskState().running(), IdleTaskRec()) | |
| wkq = Packet(None, 0, K_WORK) | |
| wkq = Packet(wkq, 0, K_WORK) | |
| WorkTask(I_WORK, 1000, wkq, TaskState( | |
| ).waitingWithPacket(), WorkerTaskRec()) | |
| wkq = Packet(None, I_DEVA, K_DEV) | |
| wkq = Packet(wkq, I_DEVA, K_DEV) | |
| wkq = Packet(wkq, I_DEVA, K_DEV) | |
| HandlerTask(I_HANDLERA, 2000, wkq, TaskState( | |
| ).waitingWithPacket(), HandlerTaskRec()) | |
| wkq = Packet(None, I_DEVB, K_DEV) | |
| wkq = Packet(wkq, I_DEVB, K_DEV) | |
| wkq = Packet(wkq, I_DEVB, K_DEV) | |
| HandlerTask(I_HANDLERB, 3000, wkq, TaskState( | |
| ).waitingWithPacket(), HandlerTaskRec()) | |
| wkq = None | |
| DeviceTask(I_DEVA, 4000, wkq, | |
| TaskState().waiting(), DeviceTaskRec()) | |
| DeviceTask(I_DEVB, 5000, wkq, | |
| TaskState().waiting(), DeviceTaskRec()) | |
| schedule() | |
| if taskWorkArea.holdCount == 9297 and taskWorkArea.qpktCount == 23246: | |
| pass | |
| else: | |
| return False | |
| return True | |
| def entry_point(iterations): | |
| r = Richards() | |
| startTime = time.time() | |
| result = r.run(iterations) | |
| endTime = time.time() | |
| return result, startTime, endTime | |
| def main(iterations=10): | |
| print("Richards benchmark (Python) starting...") | |
| result, startTime, endTime = entry_point(iterations) | |
| if not result: | |
| print("Incorrect results!") | |
| return -1 | |
| total_s = endTime - startTime | |
| print("Total time for %d iterations: %.2f secs" %(iterations,total_s)) | |
| print("Average time per iteration: %.2f ms" %(total_s*1000/iterations)) | |
| if __name__ == '__main__': | |
| import sys | |
| if len(sys.argv) >= 2: | |
| main(iterations = int(sys.argv[1])) | |
| else: | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment