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