processes.js revision effb81e5f8246d0db0270817048dc992db66e9fb
1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5processes = new (function() { 6 7this.PS_INTERVAL_SEC_ = 2; 8this.DEV_STATS_INTERVAL_SEC_ = 2; 9this.PROC_STATS_INTERVAL_SEC_ = 1; 10this.TRACER_POLL_INTERVAL_SEC_ = 2; 11 12this.selProcUri_ = null; 13this.selProcName_ = null; 14this.psTable_ = null; 15this.psTableData_ = null; 16this.memChart_ = null; 17this.memChartData_ = null; 18this.cpuChart_ = null; 19this.cpuChartData_ = null; 20this.procCpuChart_ = null; 21this.procCpuChartData_ = null; 22this.procMemChart_ = null; 23this.procMemChartData_ = null; 24this.tracerTaskId_ = null; 25 26this.onDomReady_ = function() { 27 $('#device_tabs').tabs(); 28 $('#device_tabs').on('tabsactivate', this.redrawPsStats_.bind(this)); 29 $('#device_tabs').on('tabsactivate', this.redrawDevStats_.bind(this)); 30 31 // Initialize the toolbar. 32 $('#ps-quick_snapshot').button({icons:{primary: 'ui-icon-image'}}) 33 .click(this.snapshotSelectedProcess_.bind(this)); 34 $('#ps-dump_mmaps').button({icons:{primary: 'ui-icon-calculator'}}) 35 .click(this.dumpSelectedProcessMmaps_.bind(this)); 36 $('#ps-full_profile').button({icons:{primary: 'ui-icon-clock'}}) 37 .click(this.showTracingDialog_.bind(this)); 38 39 // Set-up the tracer dialog. 40 $('#ps-tracer-dialog').dialog({autoOpen: false, modal: true, width: 400, 41 buttons: {'Start': this.startTracingSelectedProcess_.bind(this)}}); 42 $('#ps-tracer-period').spinner({min: 0, step: 20}); 43 $('#ps-tracer-snapshots').spinner({min: 1, max: 100}); 44 45 // Create the process table. 46 this.psTable_ = new google.visualization.Table($('#ps-table')[0]); 47 google.visualization.events.addListener( 48 this.psTable_, 'select', this.onPsTableRowSelect_.bind(this)); 49 $('#ps-table').on('dblclick', this.snapshotSelectedProcess_.bind(this)); 50 51 // Create the device stats charts. 52 this.memChart_ = new google.visualization.PieChart($('#os-mem_chart')[0]); 53 this.cpuChart_ = new google.visualization.BarChart($('#os-cpu_chart')[0]); 54 55 // Create the selected process stats charts. 56 this.procCpuChart_ = 57 new google.visualization.ComboChart($('#proc-cpu_chart')[0]); 58 this.procMemChart_ = 59 new google.visualization.ComboChart($('#proc-mem_chart')[0]); 60}; 61 62this.getSelectedProcessURI = function() { 63 return this.selProcUri_; 64}; 65 66this.snapshotSelectedProcess_ = function() { 67 if (!this.selProcUri_) 68 return alert('Must select a process!'); 69 mmap.dumpMmaps(this.selProcUri_, true); 70 rootUi.showTab('prof'); 71}; 72 73this.dumpSelectedProcessMmaps_ = function() { 74 if (!this.selProcUri_) 75 return alert('Must select a process!'); 76 mmap.dumpMmaps(this.selProcUri_, false); 77 rootUi.showTab('mm'); 78}; 79 80this.showTracingDialog_ = function() { 81 if (!this.selProcUri_) 82 return alert('Must select a process!'); 83 $('#ps-tracer-process').val(this.selProcName_); 84 $('#ps-tracer-dialog').dialog('open'); 85}; 86 87this.startTracingSelectedProcess_ = function() { 88 if (!this.selProcUri_) 89 return alert('The process ' + this.selProcUri_ + ' died.'); 90 91 $('#ps-tracer-dialog').dialog('close'); 92 93 var postArgs = {interval: $('#ps-tracer-period').val(), 94 count: $('#ps-tracer-snapshots').val(), 95 traceNativeHeap: false}; 96 97 webservice.ajaxRequest('/tracer/start/' + this.selProcUri_, 98 this.onStartTracerAjaxResponse_.bind(this), 99 null, // Use default error handler 100 postArgs); 101}; 102 103this.onStartTracerAjaxResponse_ = function(data) { 104 this.tracerTaskId_ = data; 105 timers.start('tracer', 106 this.pollTracerStatus_.bind(this), 107 this.TRACER_POLL_INTERVAL_SEC_); 108}; 109 110this.pollTracerStatus_ = function() { 111 if (!this.tracerTaskId_) { 112 timers.stop('tracer'); 113 return; 114 } 115 webservice.ajaxRequest('/tracer/status/' + this.tracerTaskId_, 116 this.onTracerStatusAjaxResponse_.bind(this)); 117}; 118 119this.onTracerStatusAjaxResponse_ = function(data) { 120 var logMessages = ''; 121 var completionRate = 0; 122 data.forEach(function(progress) { 123 completionRate = progress[0]; 124 logMessages += '\n' + progress[1]; 125 }, this); 126 rootUi.setProgress(completionRate); 127 rootUi.setStatusMessage(logMessages); 128 129 if (completionRate >= 100) { 130 tracerTaskId_ = null; 131 timers.stop('tracer'); 132 } 133}; 134 135this.refreshPsTable = function() { 136 var targetDevUri = devices.getSelectedURI(); 137 if (!targetDevUri) 138 return this.stopPsTable(); 139 140 var showAllParam = $('#ps-show_all').prop('checked') ? '?all=1' : ''; 141 webservice.ajaxRequest('/ps/' + targetDevUri + showAllParam, 142 this.onPsAjaxResponse_.bind(this), 143 this.stopPsTable.bind(this)); 144}; 145 146this.startPsTable = function() { 147 timers.start('ps_table', 148 this.refreshPsTable.bind(this), 149 this.PS_INTERVAL_SEC_); 150}; 151 152this.stopPsTable = function() { 153 this.selProcUri_ = null; 154 this.selProcName_ = null; 155 timers.stop('ps_table'); 156}; 157 158this.onPsTableRowSelect_ = function() { 159 var targetDevUri = devices.getSelectedURI(); 160 if (!targetDevUri) 161 return; 162 163 var sel = this.psTable_.getSelection(); 164 if (!sel.length || !this.psTableData_) 165 return; 166 var pid = this.psTableData_.getValue(sel[0].row, 0); 167 this.selProcUri_ = targetDevUri + '/' + pid; 168 this.selProcName_ = this.psTableData_.getValue(sel[0].row, 1); 169 this.startSelectedProcessStats(); 170}; 171 172this.onPsAjaxResponse_ = function(data) { 173 this.psTableData_ = new google.visualization.DataTable(data); 174 this.redrawPsTable_(); 175}; 176 177this.redrawPsTable_ = function(data) { 178 if (!this.psTableData_) 179 return; 180 181 // Redraw table preserving sorting info. 182 var sort = this.psTable_.getSortInfo() || {column: -1, ascending: false}; 183 this.psTable_.draw(this.psTableData_, {sortColumn: sort.column, 184 sortAscending: sort.ascending}); 185}; 186 187this.refreshDeviceStats = function() { 188 var targetDevUri = devices.getSelectedURI(); 189 if (!targetDevUri) 190 return this.stopDeviceStats(); 191 192 webservice.ajaxRequest('/stats/' + targetDevUri, 193 this.onDevStatsAjaxResponse_.bind(this), 194 this.stopDeviceStats.bind(this)); 195}; 196 197this.startDeviceStats = function() { 198 timers.start('device_stats', 199 this.refreshDeviceStats.bind(this), 200 this.DEV_STATS_INTERVAL_SEC_); 201}; 202 203this.stopDeviceStats = function() { 204 timers.stop('device_stats'); 205}; 206 207this.onDevStatsAjaxResponse_ = function(data) { 208 this.memChartData_ = new google.visualization.DataTable(data.mem); 209 this.cpuChartData_ = new google.visualization.DataTable(data.cpu); 210 this.redrawDevStats_(); 211}; 212 213this.redrawDevStats_ = function(data) { 214 if (!this.memChartData_ || !this.cpuChartData_) 215 return; 216 217 this.memChart_.draw(this.memChartData_, 218 {title: 'System Memory Usage (MB)', is3D: true}); 219 this.cpuChart_.draw(this.cpuChartData_, 220 {title: 'CPU Usage', 221 isStacked: true, 222 hAxis: {maxValue: 100, viewWindow: {max: 100}}}); 223}; 224 225this.refreshSelectedProcessStats = function() { 226 if (!this.selProcUri_) 227 return this.stopSelectedProcessStats(); 228 229 webservice.ajaxRequest('/stats/' + this.selProcUri_, 230 this.onPsStatsAjaxResponse_.bind(this), 231 this.stopSelectedProcessStats.bind(this)); 232}; 233 234this.startSelectedProcessStats = function() { 235 timers.start('proc_stats', 236 this.refreshSelectedProcessStats.bind(this), 237 this.PROC_STATS_INTERVAL_SEC_); 238 $('#device_tabs').tabs('option', 'active', 1); 239}; 240 241this.stopSelectedProcessStats = function() { 242 timers.stop('proc_stats'); 243}; 244 245this.onPsStatsAjaxResponse_ = function(data) { 246 this.procCpuChartData_ = new google.visualization.DataTable(data.cpu); 247 this.procMemChartData_ = new google.visualization.DataTable(data.mem); 248 this.redrawPsStats_(); 249}; 250 251this.redrawPsStats_ = function() { 252 if (!this.procCpuChartData_ || !this.procMemChartData_) 253 return; 254 255 this.procCpuChart_.draw(this.procCpuChartData_, { 256 title: 'CPU stats for ' + this.selProcUri_, 257 seriesType: 'line', 258 vAxes: {0: {title: 'CPU %', maxValue: 100}, 1: {title: '# Threads'}}, 259 series: {1: {type: 'bars', targetAxisIndex: 1}}, 260 hAxis: {title: 'Run Time'}, 261 legend: {alignment: 'end'}, 262 }); 263 this.procMemChart_.draw(this.procMemChartData_, { 264 title: 'Memory stats for ' + this.selProcUri_, 265 seriesType: 'line', 266 vAxes: {0: {title: 'VM Rss KB'}, 1: {title: '# Page Faults'}}, 267 series: {1: {type: 'bars', targetAxisIndex: 1}}, 268 hAxis: {title: 'Run Time'}, 269 legend: {alignment: 'end'}, 270 }); 271}; 272 273this.redraw = function() { 274 this.redrawPsTable_(); 275 if ($('#device_tabs').tabs('option', 'active') == 0) 276 this.redrawDevStats_(); 277 else 278 this.redrawPsStats_(); 279}; 280 281$(document).ready(this.onDomReady_.bind(this)); 282 283})();