1*288bf522SAndroid Build Coastguard Worker<!DOCTYPE html> 2*288bf522SAndroid Build Coastguard Worker<!-- 3*288bf522SAndroid Build Coastguard WorkerCopyright (C) 2015 The Android Open Source Project 4*288bf522SAndroid Build Coastguard Worker 5*288bf522SAndroid Build Coastguard WorkerLicensed under the Apache License, Version 2.0 (the "License"); 6*288bf522SAndroid Build Coastguard Workeryou may not use this file except in compliance with the License. 7*288bf522SAndroid Build Coastguard WorkerYou may obtain a copy of the License at 8*288bf522SAndroid Build Coastguard Worker 9*288bf522SAndroid Build Coastguard Worker http://www.apache.org/licenses/LICENSE-2.0 10*288bf522SAndroid Build Coastguard Worker 11*288bf522SAndroid Build Coastguard WorkerUnless required by applicable law or agreed to in writing, software 12*288bf522SAndroid Build Coastguard Workerdistributed under the License is distributed on an "AS IS" BASIS, 13*288bf522SAndroid Build Coastguard WorkerWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*288bf522SAndroid Build Coastguard WorkerSee the License for the specific language governing permissions and 15*288bf522SAndroid Build Coastguard Workerlimitations under the License. 16*288bf522SAndroid Build Coastguard Worker--> 17*288bf522SAndroid Build Coastguard Worker<link rel="import" href="/tracing/base/base.html"> 18*288bf522SAndroid Build Coastguard Worker<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html"> 19*288bf522SAndroid Build Coastguard Worker<link rel="import" href="/tracing/extras/importer/android/event_log_importer.html"> 20*288bf522SAndroid Build Coastguard Worker<link rel="import" href="/tracing/extras/android/android_auditor.html"> 21*288bf522SAndroid Build Coastguard Worker<link rel="import" href="/tracing/importer/import.html"> 22*288bf522SAndroid Build Coastguard Worker<link rel="import" href="/tracing/model/model.html"> 23*288bf522SAndroid Build Coastguard Worker<script> 24*288bf522SAndroid Build Coastguard Worker'use strict'; 25*288bf522SAndroid Build Coastguard Worker 26*288bf522SAndroid Build Coastguard Worker(function() { 27*288bf522SAndroid Build Coastguard Worker var FRAME_PERF_CLASS = tr.model.FRAME_PERF_CLASS; 28*288bf522SAndroid Build Coastguard Worker 29*288bf522SAndroid Build Coastguard Worker if (!tr.isHeadless) { 30*288bf522SAndroid Build Coastguard Worker throw new Error('Can only run in headless mode.'); 31*288bf522SAndroid Build Coastguard Worker } 32*288bf522SAndroid Build Coastguard Worker 33*288bf522SAndroid Build Coastguard Worker function printFrameStats(process, range) { 34*288bf522SAndroid Build Coastguard Worker var goodFrames = 0; 35*288bf522SAndroid Build Coastguard Worker var badFrames = 0; 36*288bf522SAndroid Build Coastguard Worker var neutralFrames = 0; 37*288bf522SAndroid Build Coastguard Worker var terribleFrames = 0; 38*288bf522SAndroid Build Coastguard Worker 39*288bf522SAndroid Build Coastguard Worker process.frames.forEach(function(frame) { 40*288bf522SAndroid Build Coastguard Worker // Check if frame belongs to any activity 41*288bf522SAndroid Build Coastguard Worker if (frame.start >= range.min && (frame.end <= range.max)) { 42*288bf522SAndroid Build Coastguard Worker if (frame.perfClass == FRAME_PERF_CLASS.NEUTRAL) neutralFrames++; 43*288bf522SAndroid Build Coastguard Worker if (frame.perfClass == FRAME_PERF_CLASS.GOOD) goodFrames++; 44*288bf522SAndroid Build Coastguard Worker if (frame.perfClass == FRAME_PERF_CLASS.BAD) badFrames++; 45*288bf522SAndroid Build Coastguard Worker if (frame.perfClass == FRAME_PERF_CLASS.TERRIBLE) terribleFrames++; 46*288bf522SAndroid Build Coastguard Worker } 47*288bf522SAndroid Build Coastguard Worker }); 48*288bf522SAndroid Build Coastguard Worker 49*288bf522SAndroid Build Coastguard Worker var totalFrames = goodFrames + badFrames + neutralFrames; 50*288bf522SAndroid Build Coastguard Worker if (totalFrames > 0) { 51*288bf522SAndroid Build Coastguard Worker console.log(" Frame stats:"); 52*288bf522SAndroid Build Coastguard Worker console.log(" # Total frames: " + totalFrames); 53*288bf522SAndroid Build Coastguard Worker console.log(" # Terrible frames: " + terribleFrames); 54*288bf522SAndroid Build Coastguard Worker console.log(" # Bad frames: " + badFrames); 55*288bf522SAndroid Build Coastguard Worker console.log(" # Neutral frames: " + neutralFrames); 56*288bf522SAndroid Build Coastguard Worker console.log(" # Good frames: " + goodFrames); 57*288bf522SAndroid Build Coastguard Worker } 58*288bf522SAndroid Build Coastguard Worker }; 59*288bf522SAndroid Build Coastguard Worker 60*288bf522SAndroid Build Coastguard Worker function printMemoryStats(process, range) { 61*288bf522SAndroid Build Coastguard Worker var numDirectReclaim = 0; 62*288bf522SAndroid Build Coastguard Worker for (var tid in process.threads) { 63*288bf522SAndroid Build Coastguard Worker if (!process.threads[tid].timeSlices) continue; 64*288bf522SAndroid Build Coastguard Worker process.threads[tid].sliceGroup.slices.forEach(function(slice) { 65*288bf522SAndroid Build Coastguard Worker if (slice.title.startsWith('direct reclaim')) { 66*288bf522SAndroid Build Coastguard Worker if (slice.start >= range.min && 67*288bf522SAndroid Build Coastguard Worker slice.start + slice.duration <= range.max) { 68*288bf522SAndroid Build Coastguard Worker numDirectReclaim++; 69*288bf522SAndroid Build Coastguard Worker } 70*288bf522SAndroid Build Coastguard Worker } 71*288bf522SAndroid Build Coastguard Worker }); 72*288bf522SAndroid Build Coastguard Worker } 73*288bf522SAndroid Build Coastguard Worker console.log(" Memory stats:"); 74*288bf522SAndroid Build Coastguard Worker console.log(" # of direct reclaims: " + numDirectReclaim); 75*288bf522SAndroid Build Coastguard Worker }; 76*288bf522SAndroid Build Coastguard Worker 77*288bf522SAndroid Build Coastguard Worker function printCpuStatsForThread(thread, range) { 78*288bf522SAndroid Build Coastguard Worker var stats = thread.getCpuStatsForRange(range); 79*288bf522SAndroid Build Coastguard Worker // Sum total CPU duration 80*288bf522SAndroid Build Coastguard Worker console.log(' ' + thread.name + ' CPU allocation: '); 81*288bf522SAndroid Build Coastguard Worker for (var cpu in stats) { 82*288bf522SAndroid Build Coastguard Worker var percentage = (stats[cpu] / stats.total * 100).toFixed(2); 83*288bf522SAndroid Build Coastguard Worker 84*288bf522SAndroid Build Coastguard Worker console.log(" CPU " + cpu + ": " + percentage + "% (" + 85*288bf522SAndroid Build Coastguard Worker stats[cpu].toFixed(2) + " ms.)"); 86*288bf522SAndroid Build Coastguard Worker } 87*288bf522SAndroid Build Coastguard Worker }; 88*288bf522SAndroid Build Coastguard Worker 89*288bf522SAndroid Build Coastguard Worker function printCpuStatsForProcess(process, range) { 90*288bf522SAndroid Build Coastguard Worker var total_runtime = 0; 91*288bf522SAndroid Build Coastguard Worker for (var tid in process.threads) { 92*288bf522SAndroid Build Coastguard Worker var stats = process.threads[tid].getCpuStatsForRange(range); 93*288bf522SAndroid Build Coastguard Worker total_runtime += stats.total; 94*288bf522SAndroid Build Coastguard Worker } 95*288bf522SAndroid Build Coastguard Worker console.log(" CPU stats:"); 96*288bf522SAndroid Build Coastguard Worker console.log(" Total CPU runtime: " + total_runtime.toFixed(2) + " ms."); 97*288bf522SAndroid Build Coastguard Worker var uiThread = process.getThread(process.pid); 98*288bf522SAndroid Build Coastguard Worker var renderThreads = process.findAllThreadsNamed('RenderThread'); 99*288bf522SAndroid Build Coastguard Worker var renderThread = renderThreads.length == 1 ? renderThreads[0] : undefined; 100*288bf522SAndroid Build Coastguard Worker if (uiThread) 101*288bf522SAndroid Build Coastguard Worker printCpuStatsForThread(uiThread, range); 102*288bf522SAndroid Build Coastguard Worker if (renderThread) 103*288bf522SAndroid Build Coastguard Worker printCpuStatsForThread(renderThread, range); 104*288bf522SAndroid Build Coastguard Worker printCpuFreqStats(range); 105*288bf522SAndroid Build Coastguard Worker }; 106*288bf522SAndroid Build Coastguard Worker 107*288bf522SAndroid Build Coastguard Worker function printCpuFreqStats(range) { 108*288bf522SAndroid Build Coastguard Worker for (var i = 0; i < 8; i++) { 109*288bf522SAndroid Build Coastguard Worker var cpu = model.kernel.getOrCreateCpu(i); 110*288bf522SAndroid Build Coastguard Worker if (cpu !== undefined) { 111*288bf522SAndroid Build Coastguard Worker var stats = cpu.getFreqStatsForRange(range); 112*288bf522SAndroid Build Coastguard Worker 113*288bf522SAndroid Build Coastguard Worker console.log(' CPU ' + i + ' frequency distribution:'); 114*288bf522SAndroid Build Coastguard Worker for (var freq in stats) { 115*288bf522SAndroid Build Coastguard Worker var percentage = (stats[freq] / range.duration * 100).toFixed(2); 116*288bf522SAndroid Build Coastguard Worker console.log(' ' + freq + ' ' + percentage + "% (" + 117*288bf522SAndroid Build Coastguard Worker stats[freq].toFixed(2) + ' ms.)'); 118*288bf522SAndroid Build Coastguard Worker } 119*288bf522SAndroid Build Coastguard Worker } 120*288bf522SAndroid Build Coastguard Worker } 121*288bf522SAndroid Build Coastguard Worker }; 122*288bf522SAndroid Build Coastguard Worker 123*288bf522SAndroid Build Coastguard Worker function printBinderStats(process, range) { 124*288bf522SAndroid Build Coastguard Worker var outgoing_transactions = 0; 125*288bf522SAndroid Build Coastguard Worker var incoming_transactions = 0; 126*288bf522SAndroid Build Coastguard Worker for (var tid in process.threads) { 127*288bf522SAndroid Build Coastguard Worker var outgoing_slices = process.threads[tid].sliceGroup.getSlicesOfName('binder transaction'); 128*288bf522SAndroid Build Coastguard Worker var outgoing_async_slices = process.threads[tid].sliceGroup.getSlicesOfName('binder transaction async'); 129*288bf522SAndroid Build Coastguard Worker var incoming_slices = process.threads[tid].sliceGroup.getSlicesOfName('binder reply'); 130*288bf522SAndroid Build Coastguard Worker var incoming_async_slices = process.threads[tid].sliceGroup.getSlicesOfName('binder Async recv'); 131*288bf522SAndroid Build Coastguard Worker outgoing_transactions += outgoing_slices.length + outgoing_async_slices.length; 132*288bf522SAndroid Build Coastguard Worker incoming_transactions += incoming_slices.length + incoming_async_slices.length; 133*288bf522SAndroid Build Coastguard Worker } 134*288bf522SAndroid Build Coastguard Worker console.log(' Binder transaction stats:'); 135*288bf522SAndroid Build Coastguard Worker console.log(' # Outgoing binder transactions: ' + outgoing_transactions); 136*288bf522SAndroid Build Coastguard Worker console.log(' # Incoming binder transactions: ' + incoming_transactions); 137*288bf522SAndroid Build Coastguard Worker }; 138*288bf522SAndroid Build Coastguard Worker 139*288bf522SAndroid Build Coastguard Worker function pagesInMBString(pages) { 140*288bf522SAndroid Build Coastguard Worker if (isNaN(pages)) 141*288bf522SAndroid Build Coastguard Worker return '0 (0.00 MB)'; 142*288bf522SAndroid Build Coastguard Worker return pages + ' (' + (pages * 4096 / 1024 / 1024).toFixed(2) + ' MB)'; 143*288bf522SAndroid Build Coastguard Worker }; 144*288bf522SAndroid Build Coastguard Worker 145*288bf522SAndroid Build Coastguard Worker function printPageCacheStats(process) { 146*288bf522SAndroid Build Coastguard Worker console.log(' Page cache stats:'); 147*288bf522SAndroid Build Coastguard Worker var totalAccess = 0; 148*288bf522SAndroid Build Coastguard Worker var totalMiss = 0; 149*288bf522SAndroid Build Coastguard Worker var totalAdd = 0; 150*288bf522SAndroid Build Coastguard Worker for (var file in process.pageCacheAccesses) { 151*288bf522SAndroid Build Coastguard Worker totalAccess += process.pageCacheAccesses[file]; 152*288bf522SAndroid Build Coastguard Worker totalMiss += process.pageCacheMisses[file]; 153*288bf522SAndroid Build Coastguard Worker totalAdd += process.pageCacheAdd[file]; 154*288bf522SAndroid Build Coastguard Worker console.log(' File: ' + file); 155*288bf522SAndroid Build Coastguard Worker console.log(' # of pages accessed: ' + pagesInMBString(process.pageCacheAccesses[file])); 156*288bf522SAndroid Build Coastguard Worker console.log(' # of pages missed: ' + pagesInMBString(process.pageCacheMisses[file])); 157*288bf522SAndroid Build Coastguard Worker console.log(' # of pages added to cache: ' + pagesInMBString(process.pageCacheAdd[file])); 158*288bf522SAndroid Build Coastguard Worker } 159*288bf522SAndroid Build Coastguard Worker console.log(' TOTALS:'); 160*288bf522SAndroid Build Coastguard Worker console.log(' # of pages accessed: ' + pagesInMBString(totalAccess)); 161*288bf522SAndroid Build Coastguard Worker console.log(' # of pages missed: ' + pagesInMBString(totalMiss)); 162*288bf522SAndroid Build Coastguard Worker console.log(' # of pages added to cache: ' + pagesInMBString(totalAdd)); 163*288bf522SAndroid Build Coastguard Worker }; 164*288bf522SAndroid Build Coastguard Worker 165*288bf522SAndroid Build Coastguard Worker function printProcessStats(process, opt_range) { 166*288bf522SAndroid Build Coastguard Worker var range = opt_range; 167*288bf522SAndroid Build Coastguard Worker if (range === undefined) { 168*288bf522SAndroid Build Coastguard Worker // Use the process range 169*288bf522SAndroid Build Coastguard Worker range = process.bounds; 170*288bf522SAndroid Build Coastguard Worker } 171*288bf522SAndroid Build Coastguard Worker printCpuStatsForProcess(process, range); 172*288bf522SAndroid Build Coastguard Worker printPageCacheStats(process); 173*288bf522SAndroid Build Coastguard Worker printMemoryStats(process, range); 174*288bf522SAndroid Build Coastguard Worker printBinderStats(process, range); 175*288bf522SAndroid Build Coastguard Worker printFrameStats(process, range); 176*288bf522SAndroid Build Coastguard Worker }; 177*288bf522SAndroid Build Coastguard Worker 178*288bf522SAndroid Build Coastguard Worker if (sys.argv.length < 2) 179*288bf522SAndroid Build Coastguard Worker console.log('First argument needs to be a systrace file.'); 180*288bf522SAndroid Build Coastguard Worker 181*288bf522SAndroid Build Coastguard Worker // Import model 182*288bf522SAndroid Build Coastguard Worker var systrace = read(sys.argv[1]); 183*288bf522SAndroid Build Coastguard Worker var traces = [systrace]; 184*288bf522SAndroid Build Coastguard Worker if (sys.argv.length >= 3) { 185*288bf522SAndroid Build Coastguard Worker // Add event log file if we got it 186*288bf522SAndroid Build Coastguard Worker var events = read(sys.argv[2]); 187*288bf522SAndroid Build Coastguard Worker traces.push(events); 188*288bf522SAndroid Build Coastguard Worker } 189*288bf522SAndroid Build Coastguard Worker var model = new tr.Model(); 190*288bf522SAndroid Build Coastguard Worker var i = new tr.importer.Import(model); 191*288bf522SAndroid Build Coastguard Worker console.log("Starting import..."); 192*288bf522SAndroid Build Coastguard Worker i.importTraces(traces); 193*288bf522SAndroid Build Coastguard Worker console.log("Done."); 194*288bf522SAndroid Build Coastguard Worker model.getAllProcesses().forEach(function(process) { 195*288bf522SAndroid Build Coastguard Worker if (process.name === undefined) return; 196*288bf522SAndroid Build Coastguard Worker console.log('Stats for process ' + process.name + ' (' + process.pid + ')'); 197*288bf522SAndroid Build Coastguard Worker // Check if process has activity starts 198*288bf522SAndroid Build Coastguard Worker if (process.activities && process.activities.length > 0) { 199*288bf522SAndroid Build Coastguard Worker process.activities.forEach(function(activity) { 200*288bf522SAndroid Build Coastguard Worker console.log('Activity ' + activity.name + ' foreground from ' + 201*288bf522SAndroid Build Coastguard Worker activity.start + ' until ' + activity.end); 202*288bf522SAndroid Build Coastguard Worker var activityRange = tr.b.Range.fromExplicitRange(activity.start, 203*288bf522SAndroid Build Coastguard Worker activity.start + activity.duration); 204*288bf522SAndroid Build Coastguard Worker printProcessStats(process, activityRange); 205*288bf522SAndroid Build Coastguard Worker }, this); 206*288bf522SAndroid Build Coastguard Worker } else { 207*288bf522SAndroid Build Coastguard Worker printProcessStats(process); 208*288bf522SAndroid Build Coastguard Worker } 209*288bf522SAndroid Build Coastguard Worker console.log(''); 210*288bf522SAndroid Build Coastguard Worker }); 211*288bf522SAndroid Build Coastguard Worker})(); 212*288bf522SAndroid Build Coastguard Worker</script> 213