Yunlian Jiang | 0861749 | 2015-10-23 10:43:45 -0700 | [diff] [blame] | 1 | #! /bin/bash -u |
| 2 | # Copyright 2015 The Chromium OS Authors. All rights reserved. |
| 3 | # Use of this source code is governed by a BSD-style license that can be |
| 4 | # found in the LICENSE file. |
| 5 | |
| 6 | # This script first collects the addresses of the instructions being tracked by |
| 7 | # the profile. After that, it calculates the offset of the addresses compared |
| 8 | # to the base address and then gets the number of execution times for each |
| 9 | # address. After that, it draws the heat map and the time map. A heap map shows |
| 10 | # the overall hotness of instructions being executed while the time map shows the |
| 11 | # hotness of instruction at different time. |
| 12 | |
| 13 | # binary : the name of the binary |
| 14 | # profile : output of 'perf report -D' |
| 15 | # loading_address : the loading address of the binary |
| 16 | # page_size : the size to be displayed, usually 4096(byte). |
| 17 | |
| 18 | if [[ $# -ne 4 ]]; then |
| 19 | echo 'Illegal number of parameters' exit 1 |
| 20 | fi |
| 21 | |
| 22 | binary=$1 |
| 23 | profile=$2 |
| 24 | loading_address=$3 |
| 25 | page_size=$4 |
| 26 | |
| 27 | # size of binary supported. |
| 28 | binary_maximum=1000000000 |
| 29 | |
| 30 | if ! [[ -e $profile ]] ; then |
| 31 | echo "error: profile does not exist" >&2; exit 1 |
| 32 | fi |
| 33 | |
| 34 | re='^[0-9]+$' |
| 35 | if ! [[ $page_size =~ $re ]] ; then |
| 36 | echo "error: page_size is not a number" >&2; exit 1 |
| 37 | fi |
| 38 | |
| 39 | function test { |
| 40 | "$@" |
| 41 | local status=$? |
| 42 | if [ $status -ne 0 ]; then |
| 43 | echo "error with $1" >&2 |
| 44 | fi |
| 45 | return $status |
| 46 | } |
| 47 | |
| 48 | HEAT_PNG="heat_map.png" |
| 49 | TIMELINE_PNG="timeline.png" |
| 50 | |
| 51 | test grep -A 2 PERF_RECORD_SAMPLE $profile | grep -A 1 -B 1 "thread: $binary" | \ |
| 52 | grep -B 2 "dso.*$binary$" | awk -v base=$loading_address \ |
| 53 | "BEGIN { count=0; } /PERF_RECORD_SAMPLE/ {addr = strtonum(\$8) - strtonum(base); \ |
| 54 | if (addr < $binary_maximum) count++; \ |
| 55 | if (addr < $binary_maximum) print \$7,count,int(addr/$page_size)*$page_size}" > out.txt |
| 56 | |
| 57 | |
| 58 | test awk '{print $3}' out.txt | sort -n | uniq -c > inst-histo.txt |
| 59 | |
| 60 | # generate inst heat map |
| 61 | echo " |
| 62 | set terminal png size 600,450 |
| 63 | set xlabel \"Instruction Virtual Address (MB)\" |
| 64 | set ylabel \"Sample Occurance\" |
| 65 | set grid |
| 66 | |
| 67 | set output \"${HEAT_PNG}\" |
| 68 | set title \"Instruction Heat Map\" |
| 69 | |
| 70 | plot 'inst-histo.txt' using (\$2/1024/1024):1 with impulses notitle |
| 71 | " | test gnuplot |
| 72 | |
| 73 | # generate instruction page access timeline |
| 74 | num=$(awk 'END {print NR+1}' out.txt) |
| 75 | |
| 76 | echo " |
| 77 | set terminal png size 600,450 |
| 78 | set xlabel \"time (sec)\" |
| 79 | set ylabel \"Instruction Virtual Address (MB)\" |
| 80 | |
| 81 | set output \"${TIMELINE_PNG}\" |
| 82 | set title \"instruction page accessd timeline\" |
| 83 | |
| 84 | plot 'out.txt' using (\$0/$num*10):(\$3/1024/1024) with dots notitle |
| 85 | " | test gnuplot |