1 #!/usr/bin/env perl 2 # SPDX-License-Identifier: GPL-2.0-only 3 4 # Copyright 2008, Intel Corporation 5 # 6 # This file is part of the Linux kernel 7 # 8 # Authors: 9 # Arjan van de Ven <arjan@linux.intel.com> 10 11 12 # 13 # This script turns a dmesg output into a SVG graphic that shows which 14 # functions take how much time. You can view SVG graphics with various 15 # programs, including Inkscape, The Gimp and Firefox. 16 # 17 # 18 # For this script to work, the kernel needs to be compiled with the 19 # CONFIG_PRINTK_TIME configuration option enabled, and with 20 # "initcall_debug" passed on the kernel command line. 21 # 22 # usage: 23 # dmesg | perl scripts/bootgraph.pl > output.svg 24 # 25 26 use strict; 27 use Getopt::Long; 28 my $header = 0; 29 30 sub help { 31 my $text = << "EOM"; 32 Usage: 33 1) dmesg | perl scripts/bootgraph.pl [OPTION] > output.svg 34 2) perl scripts/bootgraph.pl -h 35 36 Options: 37 -header Insert kernel version and date 38 EOM 39 my $std=shift; 40 if ($std == 1) { 41 print STDERR $text; 42 } else { 43 print $text; 44 } 45 exit; 46 } 47 48 GetOptions( 49 'h|help' =>\&help, 50 'header' =>\$header 51 ); 52 53 my %start; 54 my %end; 55 my %type; 56 my $done = 0; 57 my $maxtime = 0; 58 my $firsttime = 99999; 59 my $count = 0; 60 my %pids; 61 my %pidctr; 62 63 my $headerstep = 20; 64 my $xheader = 15; 65 my $yheader = 25; 66 my $cyheader = 0; 67 68 while (<>) { 69 my $line = $_; 70 if ($line =~ /([0-9\.]+)\] calling ([a-zA-Z0-9\_\.]+)\+/) { 71 my $func = $2; 72 if ($done == 0) { 73 $start{$func} = $1; 74 $type{$func} = 0; 75 if ($1 < $firsttime) { 76 $firsttime = $1; 77 } 78 } 79 if ($line =~ /\@ ([0-9]+)/) { 80 $pids{$func} = $1; 81 } 82 $count = $count + 1; 83 } 84 85 if ($line =~ /([0-9\.]+)\] async_waiting @ ([0-9]+)/) { 86 my $pid = $2; 87 my $func; 88 if (!defined($pidctr{$pid})) { 89 $func = "wait_" . $pid . "_1"; 90 $pidctr{$pid} = 1; 91 } else { 92 $pidctr{$pid} = $pidctr{$pid} + 1; 93 $func = "wait_" . $pid . "_" . $pidctr{$pid}; 94 } 95 if ($done == 0) { 96 $start{$func} = $1; 97 $type{$func} = 1; 98 if ($1 < $firsttime) { 99 $firsttime = $1; 100 } 101 } 102 $pids{$func} = $pid; 103 $count = $count + 1; 104 } 105 106 if ($line =~ /([0-9\.]+)\] initcall ([a-zA-Z0-9\_\.]+)\+.*returned/) { 107 if ($done == 0) { 108 $end{$2} = $1; 109 $maxtime = $1; 110 } 111 } 112 113 if ($line =~ /([0-9\.]+)\] async_continuing @ ([0-9]+)/) { 114 my $pid = $2; 115 my $func = "wait_" . $pid . "_" . $pidctr{$pid}; 116 $end{$func} = $1; 117 $maxtime = $1; 118 } 119 if ($line =~ /Write protecting the/) { 120 $done = 1; 121 } 122 if ($line =~ /Freeing unused kernel memory/) { 123 $done = 1; 124 } 125 } 126 127 if ($count == 0) { 128 print STDERR <<END; 129 No data found in the dmesg. Make sure that 'printk.time=1' and 130 'initcall_debug' are passed on the kernel command line. 131 END 132 help(1); 133 exit 1; 134 } 135 136 print "<?xml version=\"1.0\" standalone=\"no\"?> \n"; 137 print "<svg width=\"2000\" height=\"100%\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n"; 138 139 140 if ($header) { 141 my $version = `uname -a`; 142 my $date = `date`; 143 print "<text transform=\"translate($xheader,$yheader)\">Kernel version: $version</text>\n"; 144 $cyheader = $yheader+$headerstep; 145 print "<text transform=\"translate($xheader,$cyheader)\">Date: $date</text>\n"; 146 } 147 148 my @styles; 149 150 $styles[0] = "fill:rgb(0,0,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 151 $styles[1] = "fill:rgb(0,255,0);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 152 $styles[2] = "fill:rgb(255,0,20);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 153 $styles[3] = "fill:rgb(255,255,20);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 154 $styles[4] = "fill:rgb(255,0,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 155 $styles[5] = "fill:rgb(0,255,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 156 $styles[6] = "fill:rgb(0,128,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 157 $styles[7] = "fill:rgb(0,255,128);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 158 $styles[8] = "fill:rgb(255,0,128);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 159 $styles[9] = "fill:rgb(255,255,128);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 160 $styles[10] = "fill:rgb(255,128,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 161 $styles[11] = "fill:rgb(128,255,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)"; 162 163 my $style_wait = "fill:rgb(128,128,128);fill-opacity:0.5;stroke-width:0;stroke:rgb(0,0,0)"; 164 165 my $mult = 1950.0 / ($maxtime - $firsttime); 166 my $threshold2 = ($maxtime - $firsttime) / 120.0; 167 my $threshold = $threshold2/10; 168 my $stylecounter = 0; 169 my %rows; 170 my $rowscount = 1; 171 my @initcalls = sort { $start{$a} <=> $start{$b} } keys(%start); 172 173 foreach my $key (@initcalls) { 174 my $duration = $end{$key} - $start{$key}; 175 176 if ($duration >= $threshold) { 177 my ($s, $s2, $s3, $e, $w, $y, $y2, $style); 178 my $pid = $pids{$key}; 179 180 if (!defined($rows{$pid})) { 181 $rows{$pid} = $rowscount; 182 $rowscount = $rowscount + 1; 183 } 184 $s = ($start{$key} - $firsttime) * $mult; 185 $s2 = $s + 6; 186 $s3 = $s + 1; 187 $e = ($end{$key} - $firsttime) * $mult; 188 $w = $e - $s; 189 190 $y = $rows{$pid} * 150; 191 $y2 = $y + 4; 192 193 $style = $styles[$stylecounter]; 194 $stylecounter = $stylecounter + 1; 195 if ($stylecounter > 11) { 196 $stylecounter = 0; 197 }; 198 199 if ($type{$key} == 1) { 200 $y = $y + 15; 201 print "<rect x=\"$s\" width=\"$w\" y=\"$y\" height=\"115\" style=\"$style_wait\"/>\n"; 202 } else { 203 print "<rect x=\"$s\" width=\"$w\" y=\"$y\" height=\"145\" style=\"$style\"/>\n"; 204 if ($duration >= $threshold2) { 205 print "<text transform=\"translate($s2,$y2) rotate(90)\">$key</text>\n"; 206 } else { 207 print "<text transform=\"translate($s3,$y2) rotate(90)\" font-size=\"3pt\">$key</text>\n"; 208 } 209 } 210 } 211 } 212 213 214 # print the time line on top 215 my $time = $firsttime; 216 my $step = ($maxtime - $firsttime) / 15; 217 while ($time < $maxtime) { 218 my $s3 = ($time - $firsttime) * $mult; 219 my $tm = int($time * 100) / 100.0; 220 print "<text transform=\"translate($s3,89) rotate(90)\">$tm</text>\n"; 221 $time = $time + $step; 222 } 223 224 print "</svg>\n";
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.