Include statistical profile into profviz.
authoryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 2 Jul 2013 15:34:28 +0000 (15:34 +0000)
committeryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 2 Jul 2013 15:34:28 +0000 (15:34 +0000)
R=jkummerow@chromium.org

Review URL: https://codereview.chromium.org/17620008

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15456 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

tools/profviz/composer.js
tools/profviz/profviz.css
tools/profviz/profviz.html
tools/profviz/profviz.js
tools/profviz/worker.js
tools/tickprocessor.js

index 2f78179..72a70ea 100644 (file)
@@ -422,6 +422,7 @@ function PlotScriptComposer(kResX, kResY) {
     output("set style fill pattern 2 bo 1");
     output("set style rect fs solid 1 noborder");
     output("set style line 1 lt 1 lw 1 lc rgb \"#000000\"");
+    output("set border 15 lw 0.2");  // Draw thin border box.
     output("set xtics out nomirror");
     output("unset key");
 
index 4042f15..c583b89 100644 (file)
@@ -31,40 +31,75 @@ body {
 }
 
 #content {
-       background-color: #fff;
+  background-color: #fff;
   width: 1200px;
   margin-left: auto;
   margin-right: auto;
   padding: 25px;
 }
 
-textarea.log {
-  font-family: monospace;
+textarea {
   width: 1200px;
-  background-color: #ffe;
-  color: #000; 
   resize: none;
+  font-family: monospace;
+  font-size: 12px;
+  color: #000;
+  border: 1px dotted #aaa;
+  padding: 10px;
+  box-sizing: border-box;
 }
 
-button#start {
-  width: 100px;
+textarea.log {
+  background-color: #ffe;
 }
 
-button#reset {
+.display {
+  width: 1200px;
+  height: 600px;
+  background-color: #fff;
+  display: block;
+  box-sizing: border-box;
+}
+
+table {
+  width: 1200px;
+}
+
+button {
   width: 100px;
+  height: 20px;
+  border: 1px solid #000;
+  border-color: #aaa;
+  font-family: Verdana;
+  font-size: 12px;
+  background-color: #ddd;
+}
+
+button:hover {
+  background-color: #eee;
+}
+
+#file {
+  width: 200px;
+  height: 20px;
+  border: none;
+  font-family: Verdana;
+  font-size: 12px;
 }
 
 input.range {
-  width: 80px;
+  width: 70px;
+  height: 16px;
   text-align: right;
   padding-right: 5px;
-}
-
-table {
-  width: 1200px;
+  border: 0px;
+  background-color: #eee;
+  font-family: Verdana;
+  font-size: 12px;
 }
 
 label {
+  height: 20px;
   font-family: Verdana;
   font-size: 12px;
 }
@@ -96,3 +131,8 @@ a {
   text-decoration: none;
   color: #282;
 }
+
+a.unroll {
+  border-bottom: 1px dotted #000;
+  color: #222;
+}
index 1b9fc4d..30494f8 100644 (file)
@@ -36,24 +36,29 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -->
 <body onload="onload()">
   <div id="content">
   
-  <img src="" id="plot" type="image/svg+xml"
+  <img src="" id="plot" type="image/svg+xml" class="display"
       width="1200" height="600" class="float-right"/>
+
+  <textarea id="prof" class="display" disabled=true></textarea>
   <br/>
 
-  <table>
+  <table width="1200">
     <tr>
-      <td width="20%">
-        <button type="button" id="start" onclick="start()">
-          Start plot
+      <td width="330">
+        <button id="start" onclick="start()">
+          Start
         </button>
-        <button type="button" id="reset" onclick="ui.reset(); worker.reset();">
+        <button id="reset" onclick="ui.reset(); worker.reset();">
           Reset
         </button>
+        <button id="toggledisplay" onclick="ui.toggle();">
+          Show profile
+        </button>
       </td>
-      <td width="20%">
+      <td width="220">
         <input type="file" id="file" onchange="ui.reset();"/>
       </td>
-      <td width="30%">
+      <td width="300">
       <label title="You can manually choose the range
 to plot only part of the log file.">
         <span class="tooltip">Range</span>:
@@ -62,7 +67,7 @@ to plot only part of the log file.">
       <label>to</label>
       <input type="text" id="range_end" class="range"/>
       </td>
-      <td width="30%">
+      <td width="350">
         <label title="We model profiling overhead by accounting a constant
 execution delay to each log entry. Adjust to better suit
 your computer's performance.">
@@ -78,7 +83,11 @@ your computer's performance.">
   <textarea class="log" id="log" rows="8" disabled=true></textarea>
 
   <div class="text">
-    <h1>Instructions</h1>
+    <h1>
+      <a href="javascript:ui.info('instructions');" class="unroll">
+        Instructions
+      </a>
+    </h1>
     <div id="instructions">
     <ol>
       <li>
@@ -96,14 +105,27 @@ your computer's performance.">
         on this page. Don't worry, it won't be uploaded anywhere.
       </li>
       <li>
-        Click "Start plot" to starts number crunching. This will take a while.
+        Click "Start" to start number crunching. This will take a while.
+      </li>
+      <li>
+        Click "Show plot/profile" to switch between the statistical profile and
+        the timeline plot.<br/>
+        C++ items are missing in the statistical profile because symbol
+        information is not available.<br>
+        Consider using the
+        <a href="https://code.google.com/p/v8/wiki/V8Profiler">
+          command-line utility
+        </a> instead.
       </li>
-    </ol>
     </div>
   </div>
 
   <div class="text">
-    <h1>Credits</h1>
+    <h1>
+      <a href="javascript:ui.info('credits');" class="unroll">
+        Credits
+      </a>
+    </h1>
     <div id="credits">
     <ul>
       <li>
index cbfee7a..7af12ad 100644 (file)
@@ -29,6 +29,7 @@ var worker_scripts = [
   "../csvparser.js",
   "../splaytree.js",
   "../codemap.js",
+  "../consarray.js",
   "../profile.js",
   "../profile_view.js",
   "../logreader.js",
@@ -42,11 +43,12 @@ function plotWorker() {
   var worker = null;
 
   var delegateList = {
-    "log"     : log,
-    "error"   : logError,
-    "display" : display,
-    "range"   : setRange,
-    "script"  : scriptLoaded
+    "log"         : log,
+    "error"       : logError,
+    "displayplot" : displayplot,
+    "displayprof" : displayprof,
+    "range"       : setRange,
+    "script"      : scriptLoaded
   }
 
   function initialize() {
@@ -97,15 +99,26 @@ function UIWrapper() {
                         "start",
                         "file"];
 
-  this.log = document.getElementById("log");
-  this.plot = document.getElementById('plot');
+  var other_elements = ["log",
+                        "plot",
+                        "prof",
+                        "instructions",
+                        "credits",
+                        "toggledisplay"];
+
   for (var i in input_elements) {
     var id = input_elements[i];
     this[id] = document.getElementById(id);
   }
 
+  for (var i in other_elements) {
+    var id = other_elements[i];
+    this[id] = document.getElementById(id);
+  }
+
   this.freeze = function() {
     this.plot.style.webkitFilter = "grayscale(1)";
+    this.prof.style.color = "#bbb";
     for (var i in input_elements) {
       this[input_elements[i]].disabled = true;
     }
@@ -113,6 +126,7 @@ function UIWrapper() {
 
   this.thaw = function() {
     this.plot.style.webkitFilter = "";
+    this.prof.style.color = "#000";
     for (var i in input_elements) {
       this[input_elements[i]].disabled = false;
     }
@@ -123,6 +137,34 @@ function UIWrapper() {
     this.log.value = "";
     this.range_start.value = "automatic";
     this.range_end.value = "automatic";
+    this.toggle("plot");
+    this.plot.src = "";
+    this.prof.value = "";
+  }
+
+  this.toggle = function(mode) {
+    if (mode) this.toggledisplay.next_mode = mode;
+    if (this.toggledisplay.next_mode == "plot") {
+      this.toggledisplay.next_mode = "prof";
+      this.plot.style.display = "block";
+      this.prof.style.display = "none";
+      this.toggledisplay.innerHTML = "Show profile";
+    } else {
+      this.toggledisplay.next_mode = "plot";
+      this.plot.style.display = "none";
+      this.prof.style.display = "block";
+      this.toggledisplay.innerHTML = "Show plot";
+    }
+  }
+
+  this.info = function(field) {
+    var down_arrow = "\u25bc";
+    var right_arrow = "\u25b6";
+    if (field && this[field].style.display != "none") field = null;  // Toggle.
+    this.credits.style.display = "none";
+    this.instructions.style.display = "none";
+    if (!field) return;
+    this[field].style.display = "block";
   }
 }
 
@@ -144,7 +186,7 @@ function logError(text) {
 }
 
 
-function display(args) {
+function displayplot(args) {
   if (error_logged) {
     log("Plot failed.\n\n");
   } else {
@@ -157,6 +199,15 @@ function display(args) {
   }
 
   ui.thaw();
+  ui.toggle("plot");
+}
+
+
+function displayprof(args) {
+  if (error_logged) return;
+  ui.prof.value = args;
+  this.prof.style.color = "";
+  ui.toggle("prof");
 }
 
 
@@ -217,11 +268,12 @@ function setRange(args) {
 
 
 function onload() {
-  kResX = 1600;
-  kResY = 900;
+  kResX = 1200;
+  kResY = 600;
   error_logged = false;
   ui = new UIWrapper();
   ui.reset();
+  ui.info(null);
   worker = new plotWorker();
   worker.reset();
 }
index 5211d85..60a557f 100644 (file)
@@ -41,8 +41,13 @@ function log(text) {
 }
 
 
-function display(content) {
-  self.postMessage({ "call" : "display", "args" : content});
+function displayplot(content) {
+  self.postMessage({ "call" : "displayplot", "args" : content});
+}
+
+
+function displayprof(content) {
+  self.postMessage({ "call" : "displayprof", "args" : content});
 }
 
 
@@ -84,13 +89,42 @@ function run(args) {
          content_lines = content.split("\n");
        });
 
+  time("Producing statistical profile",
+       function() {
+         var profile = "";
+         print = function(text) { profile += text + "\n"; };
+         // Dummy entries provider, as we cannot call nm.
+         var entriesProvider = new UnixCppEntriesProvider("", "");
+         var targetRootFS = "";
+         var separateIc = false;
+         var callGraphSize = 5;
+         var ignoreUnknown = true;
+         var stateFilter = null;
+         var snapshotLogProcessor = null;
+         var range = range_start_override + "," + range_end_override;
+
+         var tickProcessor = new TickProcessor(entriesProvider,
+                                               separateIc,
+                                               callGraphSize,
+                                               ignoreUnknown,
+                                               stateFilter,
+                                               snapshotLogProcessor,
+                                               distortion,
+                                               range);
+         for (var i = 0; i < content_lines.length; i++) {
+           tickProcessor.processLogLine(content_lines[i]);
+         }
+         tickProcessor.printStatistics();
+         displayprof(profile);
+       });
+
   var input_file_name = "input_temp";
   var output_file_name = "output.svg";
 
   var psc = new PlotScriptComposer(resx, resy);
   var objects = 0;
 
-  time("Analyzing data (" + content_lines.length + " entries)",
+  time("Collecting events (" + content_lines.length + " entries)",
        function() {
          var line_cursor = 0;
          var input = function() { return content_lines[line_cursor++]; };
@@ -103,7 +137,7 @@ function run(args) {
   time("Assembling plot script",
        function() {
          var plot_script = "";
-         var output = function(output) { plot_script += output + "\n"; };
+         var output = function(text) { plot_script += text + "\n"; };
          output("set terminal svg size " + resx + "," + resy +
                 " enhanced font \"Helvetica,10\"");
          output("set output \""+ output_file_name + "\"");
@@ -115,10 +149,10 @@ function run(args) {
          FS.createDataFile("/", input_file_name, arrc);
        });
 
-  time("Running Gnuplot (" + objects + " objects)",
+  time("Running gnuplot (" + objects + " objects)",
        function() { Module.run([input_file_name]); });
 
-  display(FS.findObject(output_file_name));
+  displayplot(FS.findObject(output_file_name));
 }
 
 
@@ -131,4 +165,3 @@ var Module = {
         self.postMessage({"call": "error", "args": text});
     },
 };
-
index abb2f2d..ae654e9 100644 (file)
@@ -204,7 +204,7 @@ function TickProcessor(
   // Convert picoseconds to nanoseconds.
   this.distortion_per_entry = isNaN(distortion) ? 0 : (distortion / 1000);
   this.distortion = 0;
-  var rangelimits = range.split(",");
+  var rangelimits = range ? range.split(",") : [];
   var range_start = parseInt(rangelimits[0]);
   var range_end = parseInt(rangelimits[1]);
   // Convert milliseconds to nanoseconds.