Home | History | Annotate | Download | only in inferno
      1 <script type="text/ecmascript">
      2 function init() {
      3   var x = document.getElementsByTagName("svg")
      4   for (i = 0; i < x.length; i=i+1) {
      5       createZoomHistoryStack(x[i]);
      6   }
      7 }
      8 
      9 // Create a stack add the root svg element in it.
     10 function createZoomHistoryStack(svgElement) {
     11   stack = [];
     12   svgElement.zoomStack = stack;
     13   stack.push(svgElement.getElementById(svgElement.attributes["rootid"].value))
     14 }
     15 
     16 function dumpStack(svgElement) {
     17   // Disable (enable for debugging)
     18   return
     19   stack = svgElement.zoomStack;
     20   for (i=0 ; i < stack.length; i++) {
     21     title = stack[i].getElementsByTagName("title")[0];
     22     console.log("[" +i+ "]-" + title.textContent)
     23   }
     24 }
     25 
     26 function adjust_node_text_size(x) {
     27   title = x.getElementsByTagName("title")[0];
     28   text = x.getElementsByTagName("text")[0];
     29   rect = x.getElementsByTagName("rect")[0];
     30 
     31   width = parseFloat(rect.attributes["width"].value);
     32 
     33   // Don't even bother trying to find a best fit. The area is too small.
     34   if (width < 25) {
     35       text.textContent = "";
     36       return;
     37   }
     38   // Remove dso and #samples which are here only for mouseover purposes.
     39   methodName = title.textContent.substring(0, title.textContent.indexOf("|"));
     40 
     41   var numCharacters;
     42   for (numCharacters=methodName.length; numCharacters>4; numCharacters--) {
     43      // Avoid reflow by using hard-coded estimate instead of text.getSubStringLength(0, numCharacters)
     44      // if (text.getSubStringLength(0, numCharacters) <= width) {
     45      if (numCharacters * 7.5 <= width) {
     46        break ;
     47      }
     48   }
     49 
     50   if (numCharacters == methodName.length) {
     51     text.textContent = methodName;
     52     return
     53   }
     54 
     55   text.textContent = methodName.substring(0, numCharacters-2) + "..";
     56  }
     57 
     58 function adjust_text_size(svgElement) {
     59   var x = svgElement.getElementsByTagName("g");
     60   var i;
     61   for (i=0 ; i < x.length ; i=i+1) {
     62     adjust_node_text_size(x[i])
     63   }
     64 }
     65 
     66 function zoom(e) {
     67   svgElement = e.ownerSVGElement
     68   zoomStack = svgElement.zoomStack;
     69   zoomStack.push(e);
     70   displayFromElement(e)
     71   select(e);
     72   dumpStack(e.ownerSVGElement);
     73 
     74   // Show zoom out button.
     75   svgElement.getElementById("zoom_rect").style.display = "block";
     76   svgElement.getElementById("zoom_text").style.display = "block";
     77 }
     78 
     79 function displayFromElement(e) {
     80   var clicked_rect = e.getElementsByTagName("rect")[0];
     81   var clicked_origin_x = clicked_rect.attributes["ox"].value;
     82   var clicked_origin_y = clicked_rect.attributes["oy"].value;
     83   var clicked_origin_width = clicked_rect.attributes["owidth"].value;
     84 
     85 
     86   var svgBox = e.ownerSVGElement.getBoundingClientRect();
     87   var svgBoxHeight = svgBox.height
     88   var svgBoxWidth = svgBox.width
     89   var scaleFactor = svgBoxWidth/clicked_origin_width;
     90 
     91   var callsites = e.ownerSVGElement.getElementsByTagName("g");
     92   var i;
     93   for (i = 0; i < callsites.length; i=i+1) {
     94     text = callsites[i].getElementsByTagName("text")[0];
     95     rect = callsites[i].getElementsByTagName("rect")[0];
     96 
     97     rect_o_x = rect.attributes["ox"].value
     98     rect_o_y = parseFloat(rect.attributes["oy"].value)
     99 
    100     // Avoid multiple forced reflow by hiding nodes.
    101     if (rect_o_y > clicked_origin_y) {
    102      rect.style.display = "none"
    103      text.style.display = "none"
    104      continue;
    105     } else {
    106      rect.style.display = "block"
    107      text.style.display = "block"
    108     }
    109 
    110     rect.attributes["x"].value = newrec_x = (rect_o_x - clicked_origin_x) * scaleFactor ;
    111     rect.attributes["y"].value = newrec_y = rect_o_y + (svgBoxHeight - clicked_origin_y - 17 -2);
    112 
    113     text.attributes["y"].value = newrec_y + 12;
    114     text.attributes["x"].value = newrec_x + 4;
    115 
    116     rect.attributes["width"].value = rect.attributes["owidth"].value * scaleFactor;
    117   }
    118 
    119   adjust_text_size(e.ownerSVGElement);
    120 
    121 }
    122 
    123 function unzoom(e) {
    124 
    125   var svgOwner = e.ownerSVGElement;
    126   stack = svgOwner.zoomStack;
    127 
    128   // Unhighlight whatever was selected.
    129   if (selected != null)
    130     selected.classList.remove("s")
    131 
    132 
    133   // Stack management: Never remove the last element which is the flamegraph root.
    134   if (stack.length > 1) {
    135     previouslySelected = stack.pop();
    136     select(previouslySelected);
    137   }
    138   nextElement = stack[stack.length-1] // stack.peek()
    139 
    140   // Hide zoom out button.
    141   if (stack.length==1) {
    142     svgOwner.getElementById("zoom_rect").style.display = "none";
    143     svgOwner.getElementById("zoom_text").style.display = "none";
    144   }
    145 
    146   displayFromElement(nextElement);
    147   dumpStack(svgOwner);
    148 }
    149 
    150 function search(e) {
    151   var term = prompt("Search for:", "");
    152 
    153   var svgOwner = e.ownerSVGElement
    154   var callsites = e.ownerSVGElement.getElementsByTagName("g");
    155 
    156   if (term == null || term == "") {
    157     for (i = 0; i < callsites.length; i=i+1) {
    158       rect = callsites[i].getElementsByTagName("rect")[0];
    159       rect.attributes["fill"].value = rect.attributes["ofill"].value;
    160     }
    161     return;
    162   }
    163 
    164   for (i = 0; i < callsites.length; i=i+1) {
    165     title = callsites[i].getElementsByTagName("title")[0];
    166     rect = callsites[i].getElementsByTagName("rect")[0];
    167     if (title.textContent.indexOf(term) != -1) {
    168       rect.attributes["fill"].value = "rgb(230,100,230)";
    169     } else {
    170       rect.attributes["fill"].value = rect.attributes["ofill"].value;
    171     }
    172   }
    173 }
    174 
    175 var selected;
    176 document.onkeydown = function handle_keyboard_input(e) {
    177   if (selected == null)
    178      return;
    179 
    180   title = selected.getElementsByTagName("title")[0];
    181   nav = selected.attributes["nav"].value.split(",")
    182   navigation_index = -1
    183   switch (e.keyCode) {
    184      //case 38: // ARROW UP
    185      case 87 : navigation_index = 0;break; //W
    186 
    187      //case 32 : // ARROW LEFT
    188      case 65 : navigation_index = 1;break; //A
    189 
    190      // case 43: // ARROW DOWN
    191      case 68 : navigation_index = 3;break; // S
    192 
    193      // case 39: // ARROW RIGHT
    194      case 83 : navigation_index = 2;break; // D
    195 
    196      case 32 : zoom(selected); return false; break; // SPACE
    197 
    198      case 8: // BACKSPACE
    199           unzoom(selected); return false;
    200      default: return true;
    201   }
    202 
    203   if (nav[navigation_index] == "0")
    204     return false;
    205 
    206   target_element = selected.ownerSVGElement.getElementById(nav[navigation_index]);
    207   select(target_element)
    208   return false;
    209 }
    210 
    211 function select(e) {
    212   if (selected != null)
    213     selected.classList.remove("s")
    214   selected = e;
    215   selected.classList.add("s")
    216 
    217   // Update info bar
    218   titleElement = selected.getElementsByTagName("title")[0];
    219   text = titleElement.textContent;
    220 
    221   // Parse title
    222   method_and_info = text.split(" | ");
    223   methodName = method_and_info[0];
    224   info =  method_and_info[1]
    225 
    226   // Parse info
    227   // '/system/lib64/libhwbinder.so (4 samples: 0.28%)'
    228   var regexp = /(.*) \(.* ([0-9**\.[0-9]*%)\)/g;
    229   match = regexp.exec(info);
    230   if (match.length > 2) {
    231     percentage = match[2]
    232     // Write percentage
    233     percentageTextElement = selected.ownerSVGElement.getElementById("percent_text")
    234     percentageTextElement.textContent = percentage
    235     //console.log("'" + percentage + "'")
    236   }
    237 
    238   // Set fields
    239   barTextElement = selected.ownerSVGElement.getElementById("info_text")
    240   barTextElement.textContent = methodName
    241 }
    242 
    243 
    244 </script>