1 #!/usr/bin/env perl 1 #!/usr/bin/env perl 2 # This is a POC (proof of concept or piece of 2 # This is a POC (proof of concept or piece of crap, take your pick) for reading the 3 # text representation of trace output related 3 # text representation of trace output related to page allocation. It makes an attempt 4 # to extract some high-level information on wh 4 # to extract some high-level information on what is going on. The accuracy of the parser 5 # may vary considerably 5 # may vary considerably 6 # 6 # 7 # Example usage: trace-pagealloc-postprocess.p 7 # Example usage: trace-pagealloc-postprocess.pl < /sys/kernel/tracing/trace_pipe 8 # other options 8 # other options 9 # --prepend-parent Report on the parent p 9 # --prepend-parent Report on the parent proc and PID 10 # --read-procstat If the trace lacks pro 10 # --read-procstat If the trace lacks process info, get it from /proc 11 # --ignore-pid Aggregate processes of 11 # --ignore-pid Aggregate processes of the same name together 12 # 12 # 13 # Copyright (c) IBM Corporation 2009 13 # Copyright (c) IBM Corporation 2009 14 # Author: Mel Gorman <mel@csn.ul.ie> 14 # Author: Mel Gorman <mel@csn.ul.ie> 15 use strict; 15 use strict; 16 use Getopt::Long; 16 use Getopt::Long; 17 17 18 # Tracepoint events 18 # Tracepoint events 19 use constant MM_PAGE_ALLOC => 1; 19 use constant MM_PAGE_ALLOC => 1; 20 use constant MM_PAGE_FREE => 2; 20 use constant MM_PAGE_FREE => 2; 21 use constant MM_PAGE_FREE_BATCHED => 3; 21 use constant MM_PAGE_FREE_BATCHED => 3; 22 use constant MM_PAGE_PCPU_DRAIN => 4; 22 use constant MM_PAGE_PCPU_DRAIN => 4; 23 use constant MM_PAGE_ALLOC_ZONE_LOCKED => 5; 23 use constant MM_PAGE_ALLOC_ZONE_LOCKED => 5; 24 use constant MM_PAGE_ALLOC_EXTFRAG => 6; 24 use constant MM_PAGE_ALLOC_EXTFRAG => 6; 25 use constant EVENT_UNKNOWN => 7; 25 use constant EVENT_UNKNOWN => 7; 26 26 27 # Constants used to track state 27 # Constants used to track state 28 use constant STATE_PCPU_PAGES_DRAINED => 8; 28 use constant STATE_PCPU_PAGES_DRAINED => 8; 29 use constant STATE_PCPU_PAGES_REFILLED => 9; 29 use constant STATE_PCPU_PAGES_REFILLED => 9; 30 30 31 # High-level events extrapolated from tracepoi 31 # High-level events extrapolated from tracepoints 32 use constant HIGH_PCPU_DRAINS => 10; 32 use constant HIGH_PCPU_DRAINS => 10; 33 use constant HIGH_PCPU_REFILLS => 11; 33 use constant HIGH_PCPU_REFILLS => 11; 34 use constant HIGH_EXT_FRAGMENT => 12; 34 use constant HIGH_EXT_FRAGMENT => 12; 35 use constant HIGH_EXT_FRAGMENT_SEVERE => 13; 35 use constant HIGH_EXT_FRAGMENT_SEVERE => 13; 36 use constant HIGH_EXT_FRAGMENT_MODERATE => 14; 36 use constant HIGH_EXT_FRAGMENT_MODERATE => 14; 37 use constant HIGH_EXT_FRAGMENT_CHANGED => 15; 37 use constant HIGH_EXT_FRAGMENT_CHANGED => 15; 38 38 39 my %perprocesspid; 39 my %perprocesspid; 40 my %perprocess; 40 my %perprocess; 41 my $opt_ignorepid; 41 my $opt_ignorepid; 42 my $opt_read_procstat; 42 my $opt_read_procstat; 43 my $opt_prepend_parent; 43 my $opt_prepend_parent; 44 44 45 # Catch sigint and exit on request 45 # Catch sigint and exit on request 46 my $sigint_report = 0; 46 my $sigint_report = 0; 47 my $sigint_exit = 0; 47 my $sigint_exit = 0; 48 my $sigint_pending = 0; 48 my $sigint_pending = 0; 49 my $sigint_received = 0; 49 my $sigint_received = 0; 50 sub sigint_handler { 50 sub sigint_handler { 51 my $current_time = time; 51 my $current_time = time; 52 if ($current_time - 2 > $sigint_receiv 52 if ($current_time - 2 > $sigint_received) { 53 print "SIGINT received, report 53 print "SIGINT received, report pending. Hit ctrl-c again to exit\n"; 54 $sigint_report = 1; 54 $sigint_report = 1; 55 } else { 55 } else { 56 if (!$sigint_exit) { 56 if (!$sigint_exit) { 57 print "Second SIGINT r 57 print "Second SIGINT received quickly, exiting\n"; 58 } 58 } 59 $sigint_exit++; 59 $sigint_exit++; 60 } 60 } 61 61 62 if ($sigint_exit > 3) { 62 if ($sigint_exit > 3) { 63 print "Many SIGINTs received, 63 print "Many SIGINTs received, exiting now without report\n"; 64 exit; 64 exit; 65 } 65 } 66 66 67 $sigint_received = $current_time; 67 $sigint_received = $current_time; 68 $sigint_pending = 1; 68 $sigint_pending = 1; 69 } 69 } 70 $SIG{INT} = "sigint_handler"; 70 $SIG{INT} = "sigint_handler"; 71 71 72 # Parse command line options 72 # Parse command line options 73 GetOptions( 73 GetOptions( 74 'ignore-pid' => \$opt_ignorepi 74 'ignore-pid' => \$opt_ignorepid, 75 'read-procstat' => \$opt_read_pro 75 'read-procstat' => \$opt_read_procstat, 76 'prepend-parent' => \$opt_prepend_ 76 'prepend-parent' => \$opt_prepend_parent, 77 ); 77 ); 78 78 79 # Defaults for dynamically discovered regex's 79 # Defaults for dynamically discovered regex's 80 my $regex_fragdetails_default = 'page=([0-9a-f 80 my $regex_fragdetails_default = 'page=([0-9a-f]*) pfn=([0-9]*) alloc_order=([-0-9]*) fallback_order=([-0-9]*) pageblock_order=([-0-9]*) alloc_migratetype=([-0-9]*) fallback_migratetype=([-0-9]*) fragmenting=([-0-9]) change_ownership=([-0-9])'; 81 81 82 # Dyanically discovered regex 82 # Dyanically discovered regex 83 my $regex_fragdetails; 83 my $regex_fragdetails; 84 84 85 # Static regex used. Specified like this for r 85 # Static regex used. Specified like this for readability and for use with /o 86 # (process_pid) (cpus 86 # (process_pid) (cpus ) ( time ) (tpoint ) (details) 87 my $regex_traceevent = '\s*([a-zA-Z0-9-]*)\s*( 87 my $regex_traceevent = '\s*([a-zA-Z0-9-]*)\s*(\[[0-9]*\])\s*([0-9.]*):\s*([a-zA-Z_]*):\s*(.*)'; 88 my $regex_statname = '[-0-9]*\s\((.*)\).*'; 88 my $regex_statname = '[-0-9]*\s\((.*)\).*'; 89 my $regex_statppid = '[-0-9]*\s\(.*\)\s[A-Za-z 89 my $regex_statppid = '[-0-9]*\s\(.*\)\s[A-Za-z]\s([0-9]*).*'; 90 90 91 sub generate_traceevent_regex { 91 sub generate_traceevent_regex { 92 my $event = shift; 92 my $event = shift; 93 my $default = shift; 93 my $default = shift; 94 my $regex; 94 my $regex; 95 95 96 # Read the event format or use the def 96 # Read the event format or use the default 97 if (!open (FORMAT, "/sys/kernel/tracin 97 if (!open (FORMAT, "/sys/kernel/tracing/events/$event/format")) { 98 $regex = $default; 98 $regex = $default; 99 } else { 99 } else { 100 my $line; 100 my $line; 101 while (!eof(FORMAT)) { 101 while (!eof(FORMAT)) { 102 $line = <FORMAT>; 102 $line = <FORMAT>; 103 if ($line =~ /^print f 103 if ($line =~ /^print fmt:\s"(.*)",.*/) { 104 $regex = $1; 104 $regex = $1; 105 $regex =~ s/%p 105 $regex =~ s/%p/\([0-9a-f]*\)/g; 106 $regex =~ s/%d 106 $regex =~ s/%d/\([-0-9]*\)/g; 107 $regex =~ s/%l 107 $regex =~ s/%lu/\([0-9]*\)/g; 108 } 108 } 109 } 109 } 110 } 110 } 111 111 112 # Verify fields are in the right order 112 # Verify fields are in the right order 113 my $tuple; 113 my $tuple; 114 foreach $tuple (split /\s/, $regex) { 114 foreach $tuple (split /\s/, $regex) { 115 my ($key, $value) = split(/=/, 115 my ($key, $value) = split(/=/, $tuple); 116 my $expected = shift; 116 my $expected = shift; 117 if ($key ne $expected) { 117 if ($key ne $expected) { 118 print("WARNING: Format 118 print("WARNING: Format not as expected '$key' != '$expected'"); 119 $regex =~ s/$key=\((.* 119 $regex =~ s/$key=\((.*)\)/$key=$1/; 120 } 120 } 121 } 121 } 122 122 123 if (defined shift) { 123 if (defined shift) { 124 die("Fewer fields than expecte 124 die("Fewer fields than expected in format"); 125 } 125 } 126 126 127 return $regex; 127 return $regex; 128 } 128 } 129 $regex_fragdetails = generate_traceevent_regex 129 $regex_fragdetails = generate_traceevent_regex("kmem/mm_page_alloc_extfrag", 130 $regex_fragdetails_def 130 $regex_fragdetails_default, 131 "page", "pfn", 131 "page", "pfn", 132 "alloc_order", "fallba 132 "alloc_order", "fallback_order", "pageblock_order", 133 "alloc_migratetype", " 133 "alloc_migratetype", "fallback_migratetype", 134 "fragmenting", "change 134 "fragmenting", "change_ownership"); 135 135 136 sub read_statline($) { 136 sub read_statline($) { 137 my $pid = $_[0]; 137 my $pid = $_[0]; 138 my $statline; 138 my $statline; 139 139 140 if (open(STAT, "/proc/$pid/stat")) { 140 if (open(STAT, "/proc/$pid/stat")) { 141 $statline = <STAT>; 141 $statline = <STAT>; 142 close(STAT); 142 close(STAT); 143 } 143 } 144 144 145 if ($statline eq '') { 145 if ($statline eq '') { 146 $statline = "-1 (UNKNOWN_PROCE 146 $statline = "-1 (UNKNOWN_PROCESS_NAME) R 0"; 147 } 147 } 148 148 149 return $statline; 149 return $statline; 150 } 150 } 151 151 152 sub guess_process_pid($$) { 152 sub guess_process_pid($$) { 153 my $pid = $_[0]; 153 my $pid = $_[0]; 154 my $statline = $_[1]; 154 my $statline = $_[1]; 155 155 156 if ($pid == 0) { 156 if ($pid == 0) { 157 return "swapper-0"; 157 return "swapper-0"; 158 } 158 } 159 159 160 if ($statline !~ /$regex_statname/o) { 160 if ($statline !~ /$regex_statname/o) { 161 die("Failed to math stat line 161 die("Failed to math stat line for process name :: $statline"); 162 } 162 } 163 return "$1-$pid"; 163 return "$1-$pid"; 164 } 164 } 165 165 166 sub parent_info($$) { 166 sub parent_info($$) { 167 my $pid = $_[0]; 167 my $pid = $_[0]; 168 my $statline = $_[1]; 168 my $statline = $_[1]; 169 my $ppid; 169 my $ppid; 170 170 171 if ($pid == 0) { 171 if ($pid == 0) { 172 return "NOPARENT-0"; 172 return "NOPARENT-0"; 173 } 173 } 174 174 175 if ($statline !~ /$regex_statppid/o) { 175 if ($statline !~ /$regex_statppid/o) { 176 die("Failed to match stat line 176 die("Failed to match stat line process ppid:: $statline"); 177 } 177 } 178 178 179 # Read the ppid stat line 179 # Read the ppid stat line 180 $ppid = $1; 180 $ppid = $1; 181 return guess_process_pid($ppid, read_s 181 return guess_process_pid($ppid, read_statline($ppid)); 182 } 182 } 183 183 184 sub process_events { 184 sub process_events { 185 my $traceevent; 185 my $traceevent; 186 my $process_pid; 186 my $process_pid; 187 my $cpus; 187 my $cpus; 188 my $timestamp; 188 my $timestamp; 189 my $tracepoint; 189 my $tracepoint; 190 my $details; 190 my $details; 191 my $statline; 191 my $statline; 192 192 193 # Read each line of the event log 193 # Read each line of the event log 194 EVENT_PROCESS: 194 EVENT_PROCESS: 195 while ($traceevent = <STDIN>) { 195 while ($traceevent = <STDIN>) { 196 if ($traceevent =~ /$regex_tra 196 if ($traceevent =~ /$regex_traceevent/o) { 197 $process_pid = $1; 197 $process_pid = $1; 198 $tracepoint = $4; 198 $tracepoint = $4; 199 199 200 if ($opt_read_procstat 200 if ($opt_read_procstat || $opt_prepend_parent) { 201 $process_pid = 201 $process_pid =~ /(.*)-([0-9]*)$/; 202 my $process = 202 my $process = $1; 203 my $pid = $2; 203 my $pid = $2; 204 204 205 $statline = re 205 $statline = read_statline($pid); 206 206 207 if ($opt_read_ 207 if ($opt_read_procstat && $process eq '') { 208 $proce 208 $process_pid = guess_process_pid($pid, $statline); 209 } 209 } 210 210 211 if ($opt_prepe 211 if ($opt_prepend_parent) { 212 $proce 212 $process_pid = parent_info($pid, $statline) . " :: $process_pid"; 213 } 213 } 214 } 214 } 215 215 216 # Unnecessary in this 216 # Unnecessary in this script. Uncomment if required 217 # $cpus = $2; 217 # $cpus = $2; 218 # $timestamp = $3; 218 # $timestamp = $3; 219 } else { 219 } else { 220 next; 220 next; 221 } 221 } 222 222 223 # Perl Switch() sucks majorly 223 # Perl Switch() sucks majorly 224 if ($tracepoint eq "mm_page_al 224 if ($tracepoint eq "mm_page_alloc") { 225 $perprocesspid{$proces 225 $perprocesspid{$process_pid}->{MM_PAGE_ALLOC}++; 226 } elsif ($tracepoint eq "mm_pa 226 } elsif ($tracepoint eq "mm_page_free") { 227 $perprocesspid{$proces 227 $perprocesspid{$process_pid}->{MM_PAGE_FREE}++ 228 } elsif ($tracepoint eq "mm_pa 228 } elsif ($tracepoint eq "mm_page_free_batched") { 229 $perprocesspid{$proces 229 $perprocesspid{$process_pid}->{MM_PAGE_FREE_BATCHED}++; 230 } elsif ($tracepoint eq "mm_pa 230 } elsif ($tracepoint eq "mm_page_pcpu_drain") { 231 $perprocesspid{$proces 231 $perprocesspid{$process_pid}->{MM_PAGE_PCPU_DRAIN}++; 232 $perprocesspid{$proces 232 $perprocesspid{$process_pid}->{STATE_PCPU_PAGES_DRAINED}++; 233 } elsif ($tracepoint eq "mm_pa 233 } elsif ($tracepoint eq "mm_page_alloc_zone_locked") { 234 $perprocesspid{$proces 234 $perprocesspid{$process_pid}->{MM_PAGE_ALLOC_ZONE_LOCKED}++; 235 $perprocesspid{$proces 235 $perprocesspid{$process_pid}->{STATE_PCPU_PAGES_REFILLED}++; 236 } elsif ($tracepoint eq "mm_pa 236 } elsif ($tracepoint eq "mm_page_alloc_extfrag") { 237 237 238 # Extract the details 238 # Extract the details of the event now 239 $details = $5; 239 $details = $5; 240 240 241 my ($page, $pfn); 241 my ($page, $pfn); 242 my ($alloc_order, $fal 242 my ($alloc_order, $fallback_order, $pageblock_order); 243 my ($alloc_migratetype 243 my ($alloc_migratetype, $fallback_migratetype); 244 my ($fragmenting, $cha 244 my ($fragmenting, $change_ownership); 245 245 246 if ($details !~ /$rege 246 if ($details !~ /$regex_fragdetails/o) { 247 print "WARNING 247 print "WARNING: Failed to parse mm_page_alloc_extfrag as expected\n"; 248 next; 248 next; 249 } 249 } 250 250 251 $perprocesspid{$proces 251 $perprocesspid{$process_pid}->{MM_PAGE_ALLOC_EXTFRAG}++; 252 $page = $1; 252 $page = $1; 253 $pfn = $2; 253 $pfn = $2; 254 $alloc_order = $3; 254 $alloc_order = $3; 255 $fallback_order = $4; 255 $fallback_order = $4; 256 $pageblock_order = $5; 256 $pageblock_order = $5; 257 $alloc_migratetype = $ 257 $alloc_migratetype = $6; 258 $fallback_migratetype 258 $fallback_migratetype = $7; 259 $fragmenting = $8; 259 $fragmenting = $8; 260 $change_ownership = $9 260 $change_ownership = $9; 261 261 262 if ($fragmenting) { 262 if ($fragmenting) { 263 $perprocesspid 263 $perprocesspid{$process_pid}->{HIGH_EXT_FRAG}++; 264 if ($fallback_ 264 if ($fallback_order <= 3) { 265 $perpr 265 $perprocesspid{$process_pid}->{HIGH_EXT_FRAGMENT_SEVERE}++; 266 } else { 266 } else { 267 $perpr 267 $perprocesspid{$process_pid}->{HIGH_EXT_FRAGMENT_MODERATE}++; 268 } 268 } 269 } 269 } 270 if ($change_ownership) 270 if ($change_ownership) { 271 $perprocesspid 271 $perprocesspid{$process_pid}->{HIGH_EXT_FRAGMENT_CHANGED}++; 272 } 272 } 273 } else { 273 } else { 274 $perprocesspid{$proces 274 $perprocesspid{$process_pid}->{EVENT_UNKNOWN}++; 275 } 275 } 276 276 277 # Catch a full pcpu drain even 277 # Catch a full pcpu drain event 278 if ($perprocesspid{$process_pi 278 if ($perprocesspid{$process_pid}->{STATE_PCPU_PAGES_DRAINED} && 279 $tracepoint ne 279 $tracepoint ne "mm_page_pcpu_drain") { 280 280 281 $perprocesspid{$proces 281 $perprocesspid{$process_pid}->{HIGH_PCPU_DRAINS}++; 282 $perprocesspid{$proces 282 $perprocesspid{$process_pid}->{STATE_PCPU_PAGES_DRAINED} = 0; 283 } 283 } 284 284 285 # Catch a full pcpu refill eve 285 # Catch a full pcpu refill event 286 if ($perprocesspid{$process_pi 286 if ($perprocesspid{$process_pid}->{STATE_PCPU_PAGES_REFILLED} && 287 $tracepoint ne 287 $tracepoint ne "mm_page_alloc_zone_locked") { 288 $perprocesspid{$proces 288 $perprocesspid{$process_pid}->{HIGH_PCPU_REFILLS}++; 289 $perprocesspid{$proces 289 $perprocesspid{$process_pid}->{STATE_PCPU_PAGES_REFILLED} = 0; 290 } 290 } 291 291 292 if ($sigint_pending) { 292 if ($sigint_pending) { 293 last EVENT_PROCESS; 293 last EVENT_PROCESS; 294 } 294 } 295 } 295 } 296 } 296 } 297 297 298 sub dump_stats { 298 sub dump_stats { 299 my $hashref = shift; 299 my $hashref = shift; 300 my %stats = %$hashref; 300 my %stats = %$hashref; 301 301 302 # Dump per-process stats 302 # Dump per-process stats 303 my $process_pid; 303 my $process_pid; 304 my $max_strlen = 0; 304 my $max_strlen = 0; 305 305 306 # Get the maximum process name 306 # Get the maximum process name 307 foreach $process_pid (keys %perprocess 307 foreach $process_pid (keys %perprocesspid) { 308 my $len = length($process_pid) 308 my $len = length($process_pid); 309 if ($len > $max_strlen) { 309 if ($len > $max_strlen) { 310 $max_strlen = $len; 310 $max_strlen = $len; 311 } 311 } 312 } 312 } 313 $max_strlen += 2; 313 $max_strlen += 2; 314 314 315 printf("\n"); 315 printf("\n"); 316 printf("%-" . $max_strlen . "s %8s %10 316 printf("%-" . $max_strlen . "s %8s %10s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s\n", 317 "Process", "Pages", "Pages", 317 "Process", "Pages", "Pages", "Pages", "Pages", "PCPU", "PCPU", "PCPU", "Fragment", "Fragment", "MigType", "Fragment", "Fragment", "Unknown"); 318 printf("%-" . $max_strlen . "s %8s %10 318 printf("%-" . $max_strlen . "s %8s %10s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s\n", 319 "details", "allocd", "allocd", 319 "details", "allocd", "allocd", "freed", "freed", "pages", "drains", "refills", "Fallback", "Causing", "Changed", "Severe", "Moderate", ""); 320 320 321 printf("%-" . $max_strlen . "s %8s %10 321 printf("%-" . $max_strlen . "s %8s %10s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s\n", 322 "", "", "under lo 322 "", "", "under lock", "direct", "pagevec", "drain", "", "", "", "", "", "", "", ""); 323 323 324 foreach $process_pid (keys %stats) { 324 foreach $process_pid (keys %stats) { 325 # Dump final aggregates 325 # Dump final aggregates 326 if ($stats{$process_pid}->{STA 326 if ($stats{$process_pid}->{STATE_PCPU_PAGES_DRAINED}) { 327 $stats{$process_pid}-> 327 $stats{$process_pid}->{HIGH_PCPU_DRAINS}++; 328 $stats{$process_pid}-> 328 $stats{$process_pid}->{STATE_PCPU_PAGES_DRAINED} = 0; 329 } 329 } 330 if ($stats{$process_pid}->{STA 330 if ($stats{$process_pid}->{STATE_PCPU_PAGES_REFILLED}) { 331 $stats{$process_pid}-> 331 $stats{$process_pid}->{HIGH_PCPU_REFILLS}++; 332 $stats{$process_pid}-> 332 $stats{$process_pid}->{STATE_PCPU_PAGES_REFILLED} = 0; 333 } 333 } 334 334 335 printf("%-" . $max_strlen . "s 335 printf("%-" . $max_strlen . "s %8d %10d %8d %8d %8d %8d %8d %8d %8d %8d %8d %8d %8d\n", 336 $process_pid, 336 $process_pid, 337 $stats{$process_pid}-> 337 $stats{$process_pid}->{MM_PAGE_ALLOC}, 338 $stats{$process_pid}-> 338 $stats{$process_pid}->{MM_PAGE_ALLOC_ZONE_LOCKED}, 339 $stats{$process_pid}-> 339 $stats{$process_pid}->{MM_PAGE_FREE}, 340 $stats{$process_pid}-> 340 $stats{$process_pid}->{MM_PAGE_FREE_BATCHED}, 341 $stats{$process_pid}-> 341 $stats{$process_pid}->{MM_PAGE_PCPU_DRAIN}, 342 $stats{$process_pid}-> 342 $stats{$process_pid}->{HIGH_PCPU_DRAINS}, 343 $stats{$process_pid}-> 343 $stats{$process_pid}->{HIGH_PCPU_REFILLS}, 344 $stats{$process_pid}-> 344 $stats{$process_pid}->{MM_PAGE_ALLOC_EXTFRAG}, 345 $stats{$process_pid}-> 345 $stats{$process_pid}->{HIGH_EXT_FRAG}, 346 $stats{$process_pid}-> 346 $stats{$process_pid}->{HIGH_EXT_FRAGMENT_CHANGED}, 347 $stats{$process_pid}-> 347 $stats{$process_pid}->{HIGH_EXT_FRAGMENT_SEVERE}, 348 $stats{$process_pid}-> 348 $stats{$process_pid}->{HIGH_EXT_FRAGMENT_MODERATE}, 349 $stats{$process_pid}-> 349 $stats{$process_pid}->{EVENT_UNKNOWN}); 350 } 350 } 351 } 351 } 352 352 353 sub aggregate_perprocesspid() { 353 sub aggregate_perprocesspid() { 354 my $process_pid; 354 my $process_pid; 355 my $process; 355 my $process; 356 undef %perprocess; 356 undef %perprocess; 357 357 358 foreach $process_pid (keys %perprocess 358 foreach $process_pid (keys %perprocesspid) { 359 $process = $process_pid; 359 $process = $process_pid; 360 $process =~ s/-([0-9])*$//; 360 $process =~ s/-([0-9])*$//; 361 if ($process eq '') { 361 if ($process eq '') { 362 $process = "NO_PROCESS 362 $process = "NO_PROCESS_NAME"; 363 } 363 } 364 364 365 $perprocess{$process}->{MM_PAG 365 $perprocess{$process}->{MM_PAGE_ALLOC} += $perprocesspid{$process_pid}->{MM_PAGE_ALLOC}; 366 $perprocess{$process}->{MM_PAG 366 $perprocess{$process}->{MM_PAGE_ALLOC_ZONE_LOCKED} += $perprocesspid{$process_pid}->{MM_PAGE_ALLOC_ZONE_LOCKED}; 367 $perprocess{$process}->{MM_PAG 367 $perprocess{$process}->{MM_PAGE_FREE} += $perprocesspid{$process_pid}->{MM_PAGE_FREE}; 368 $perprocess{$process}->{MM_PAG 368 $perprocess{$process}->{MM_PAGE_FREE_BATCHED} += $perprocesspid{$process_pid}->{MM_PAGE_FREE_BATCHED}; 369 $perprocess{$process}->{MM_PAG 369 $perprocess{$process}->{MM_PAGE_PCPU_DRAIN} += $perprocesspid{$process_pid}->{MM_PAGE_PCPU_DRAIN}; 370 $perprocess{$process}->{HIGH_P 370 $perprocess{$process}->{HIGH_PCPU_DRAINS} += $perprocesspid{$process_pid}->{HIGH_PCPU_DRAINS}; 371 $perprocess{$process}->{HIGH_P 371 $perprocess{$process}->{HIGH_PCPU_REFILLS} += $perprocesspid{$process_pid}->{HIGH_PCPU_REFILLS}; 372 $perprocess{$process}->{MM_PAG 372 $perprocess{$process}->{MM_PAGE_ALLOC_EXTFRAG} += $perprocesspid{$process_pid}->{MM_PAGE_ALLOC_EXTFRAG}; 373 $perprocess{$process}->{HIGH_E 373 $perprocess{$process}->{HIGH_EXT_FRAG} += $perprocesspid{$process_pid}->{HIGH_EXT_FRAG}; 374 $perprocess{$process}->{HIGH_E 374 $perprocess{$process}->{HIGH_EXT_FRAGMENT_CHANGED} += $perprocesspid{$process_pid}->{HIGH_EXT_FRAGMENT_CHANGED}; 375 $perprocess{$process}->{HIGH_E 375 $perprocess{$process}->{HIGH_EXT_FRAGMENT_SEVERE} += $perprocesspid{$process_pid}->{HIGH_EXT_FRAGMENT_SEVERE}; 376 $perprocess{$process}->{HIGH_E 376 $perprocess{$process}->{HIGH_EXT_FRAGMENT_MODERATE} += $perprocesspid{$process_pid}->{HIGH_EXT_FRAGMENT_MODERATE}; 377 $perprocess{$process}->{EVENT_ 377 $perprocess{$process}->{EVENT_UNKNOWN} += $perprocesspid{$process_pid}->{EVENT_UNKNOWN}; 378 } 378 } 379 } 379 } 380 380 381 sub report() { 381 sub report() { 382 if (!$opt_ignorepid) { 382 if (!$opt_ignorepid) { 383 dump_stats(\%perprocesspid); 383 dump_stats(\%perprocesspid); 384 } else { 384 } else { 385 aggregate_perprocesspid(); 385 aggregate_perprocesspid(); 386 dump_stats(\%perprocess); 386 dump_stats(\%perprocess); 387 } 387 } 388 } 388 } 389 389 390 # Process events or signals until neither is a 390 # Process events or signals until neither is available 391 sub signal_loop() { 391 sub signal_loop() { 392 my $sigint_processed; 392 my $sigint_processed; 393 do { 393 do { 394 $sigint_processed = 0; 394 $sigint_processed = 0; 395 process_events(); 395 process_events(); 396 396 397 # Handle pending signals if an 397 # Handle pending signals if any 398 if ($sigint_pending) { 398 if ($sigint_pending) { 399 my $current_time = tim 399 my $current_time = time; 400 400 401 if ($sigint_exit) { 401 if ($sigint_exit) { 402 print "Receive 402 print "Received exit signal\n"; 403 $sigint_pendin 403 $sigint_pending = 0; 404 } 404 } 405 if ($sigint_report) { 405 if ($sigint_report) { 406 if ($current_t 406 if ($current_time >= $sigint_received + 2) { 407 report 407 report(); 408 $sigin 408 $sigint_report = 0; 409 $sigin 409 $sigint_pending = 0; 410 $sigin 410 $sigint_processed = 1; 411 } 411 } 412 } 412 } 413 } 413 } 414 } while ($sigint_pending || $sigint_pr 414 } while ($sigint_pending || $sigint_processed); 415 } 415 } 416 416 417 signal_loop(); 417 signal_loop(); 418 report(); 418 report();
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.