18c2ecf20Sopenharmony_ci#!/usr/bin/env perl 28c2ecf20Sopenharmony_ci# This is a POC (proof of concept or piece of crap, take your pick) for reading the 38c2ecf20Sopenharmony_ci# text representation of trace output related to page allocation. It makes an attempt 48c2ecf20Sopenharmony_ci# to extract some high-level information on what is going on. The accuracy of the parser 58c2ecf20Sopenharmony_ci# may vary considerably 68c2ecf20Sopenharmony_ci# 78c2ecf20Sopenharmony_ci# Example usage: trace-pagealloc-postprocess.pl < /sys/kernel/debug/tracing/trace_pipe 88c2ecf20Sopenharmony_ci# other options 98c2ecf20Sopenharmony_ci# --prepend-parent Report on the parent proc and PID 108c2ecf20Sopenharmony_ci# --read-procstat If the trace lacks process info, get it from /proc 118c2ecf20Sopenharmony_ci# --ignore-pid Aggregate processes of the same name together 128c2ecf20Sopenharmony_ci# 138c2ecf20Sopenharmony_ci# Copyright (c) IBM Corporation 2009 148c2ecf20Sopenharmony_ci# Author: Mel Gorman <mel@csn.ul.ie> 158c2ecf20Sopenharmony_ciuse strict; 168c2ecf20Sopenharmony_ciuse Getopt::Long; 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci# Tracepoint events 198c2ecf20Sopenharmony_ciuse constant MM_PAGE_ALLOC => 1; 208c2ecf20Sopenharmony_ciuse constant MM_PAGE_FREE => 2; 218c2ecf20Sopenharmony_ciuse constant MM_PAGE_FREE_BATCHED => 3; 228c2ecf20Sopenharmony_ciuse constant MM_PAGE_PCPU_DRAIN => 4; 238c2ecf20Sopenharmony_ciuse constant MM_PAGE_ALLOC_ZONE_LOCKED => 5; 248c2ecf20Sopenharmony_ciuse constant MM_PAGE_ALLOC_EXTFRAG => 6; 258c2ecf20Sopenharmony_ciuse constant EVENT_UNKNOWN => 7; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci# Constants used to track state 288c2ecf20Sopenharmony_ciuse constant STATE_PCPU_PAGES_DRAINED => 8; 298c2ecf20Sopenharmony_ciuse constant STATE_PCPU_PAGES_REFILLED => 9; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci# High-level events extrapolated from tracepoints 328c2ecf20Sopenharmony_ciuse constant HIGH_PCPU_DRAINS => 10; 338c2ecf20Sopenharmony_ciuse constant HIGH_PCPU_REFILLS => 11; 348c2ecf20Sopenharmony_ciuse constant HIGH_EXT_FRAGMENT => 12; 358c2ecf20Sopenharmony_ciuse constant HIGH_EXT_FRAGMENT_SEVERE => 13; 368c2ecf20Sopenharmony_ciuse constant HIGH_EXT_FRAGMENT_MODERATE => 14; 378c2ecf20Sopenharmony_ciuse constant HIGH_EXT_FRAGMENT_CHANGED => 15; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cimy %perprocesspid; 408c2ecf20Sopenharmony_cimy %perprocess; 418c2ecf20Sopenharmony_cimy $opt_ignorepid; 428c2ecf20Sopenharmony_cimy $opt_read_procstat; 438c2ecf20Sopenharmony_cimy $opt_prepend_parent; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci# Catch sigint and exit on request 468c2ecf20Sopenharmony_cimy $sigint_report = 0; 478c2ecf20Sopenharmony_cimy $sigint_exit = 0; 488c2ecf20Sopenharmony_cimy $sigint_pending = 0; 498c2ecf20Sopenharmony_cimy $sigint_received = 0; 508c2ecf20Sopenharmony_cisub sigint_handler { 518c2ecf20Sopenharmony_ci my $current_time = time; 528c2ecf20Sopenharmony_ci if ($current_time - 2 > $sigint_received) { 538c2ecf20Sopenharmony_ci print "SIGINT received, report pending. Hit ctrl-c again to exit\n"; 548c2ecf20Sopenharmony_ci $sigint_report = 1; 558c2ecf20Sopenharmony_ci } else { 568c2ecf20Sopenharmony_ci if (!$sigint_exit) { 578c2ecf20Sopenharmony_ci print "Second SIGINT received quickly, exiting\n"; 588c2ecf20Sopenharmony_ci } 598c2ecf20Sopenharmony_ci $sigint_exit++; 608c2ecf20Sopenharmony_ci } 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci if ($sigint_exit > 3) { 638c2ecf20Sopenharmony_ci print "Many SIGINTs received, exiting now without report\n"; 648c2ecf20Sopenharmony_ci exit; 658c2ecf20Sopenharmony_ci } 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci $sigint_received = $current_time; 688c2ecf20Sopenharmony_ci $sigint_pending = 1; 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_ci$SIG{INT} = "sigint_handler"; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci# Parse command line options 738c2ecf20Sopenharmony_ciGetOptions( 748c2ecf20Sopenharmony_ci 'ignore-pid' => \$opt_ignorepid, 758c2ecf20Sopenharmony_ci 'read-procstat' => \$opt_read_procstat, 768c2ecf20Sopenharmony_ci 'prepend-parent' => \$opt_prepend_parent, 778c2ecf20Sopenharmony_ci); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci# Defaults for dynamically discovered regex's 808c2ecf20Sopenharmony_cimy $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])'; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci# Dyanically discovered regex 838c2ecf20Sopenharmony_cimy $regex_fragdetails; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci# Static regex used. Specified like this for readability and for use with /o 868c2ecf20Sopenharmony_ci# (process_pid) (cpus ) ( time ) (tpoint ) (details) 878c2ecf20Sopenharmony_cimy $regex_traceevent = '\s*([a-zA-Z0-9-]*)\s*(\[[0-9]*\])\s*([0-9.]*):\s*([a-zA-Z_]*):\s*(.*)'; 888c2ecf20Sopenharmony_cimy $regex_statname = '[-0-9]*\s\((.*)\).*'; 898c2ecf20Sopenharmony_cimy $regex_statppid = '[-0-9]*\s\(.*\)\s[A-Za-z]\s([0-9]*).*'; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cisub generate_traceevent_regex { 928c2ecf20Sopenharmony_ci my $event = shift; 938c2ecf20Sopenharmony_ci my $default = shift; 948c2ecf20Sopenharmony_ci my $regex; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci # Read the event format or use the default 978c2ecf20Sopenharmony_ci if (!open (FORMAT, "/sys/kernel/debug/tracing/events/$event/format")) { 988c2ecf20Sopenharmony_ci $regex = $default; 998c2ecf20Sopenharmony_ci } else { 1008c2ecf20Sopenharmony_ci my $line; 1018c2ecf20Sopenharmony_ci while (!eof(FORMAT)) { 1028c2ecf20Sopenharmony_ci $line = <FORMAT>; 1038c2ecf20Sopenharmony_ci if ($line =~ /^print fmt:\s"(.*)",.*/) { 1048c2ecf20Sopenharmony_ci $regex = $1; 1058c2ecf20Sopenharmony_ci $regex =~ s/%p/\([0-9a-f]*\)/g; 1068c2ecf20Sopenharmony_ci $regex =~ s/%d/\([-0-9]*\)/g; 1078c2ecf20Sopenharmony_ci $regex =~ s/%lu/\([0-9]*\)/g; 1088c2ecf20Sopenharmony_ci } 1098c2ecf20Sopenharmony_ci } 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci # Verify fields are in the right order 1138c2ecf20Sopenharmony_ci my $tuple; 1148c2ecf20Sopenharmony_ci foreach $tuple (split /\s/, $regex) { 1158c2ecf20Sopenharmony_ci my ($key, $value) = split(/=/, $tuple); 1168c2ecf20Sopenharmony_ci my $expected = shift; 1178c2ecf20Sopenharmony_ci if ($key ne $expected) { 1188c2ecf20Sopenharmony_ci print("WARNING: Format not as expected '$key' != '$expected'"); 1198c2ecf20Sopenharmony_ci $regex =~ s/$key=\((.*)\)/$key=$1/; 1208c2ecf20Sopenharmony_ci } 1218c2ecf20Sopenharmony_ci } 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci if (defined shift) { 1248c2ecf20Sopenharmony_ci die("Fewer fields than expected in format"); 1258c2ecf20Sopenharmony_ci } 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci return $regex; 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ci$regex_fragdetails = generate_traceevent_regex("kmem/mm_page_alloc_extfrag", 1308c2ecf20Sopenharmony_ci $regex_fragdetails_default, 1318c2ecf20Sopenharmony_ci "page", "pfn", 1328c2ecf20Sopenharmony_ci "alloc_order", "fallback_order", "pageblock_order", 1338c2ecf20Sopenharmony_ci "alloc_migratetype", "fallback_migratetype", 1348c2ecf20Sopenharmony_ci "fragmenting", "change_ownership"); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cisub read_statline($) { 1378c2ecf20Sopenharmony_ci my $pid = $_[0]; 1388c2ecf20Sopenharmony_ci my $statline; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci if (open(STAT, "/proc/$pid/stat")) { 1418c2ecf20Sopenharmony_ci $statline = <STAT>; 1428c2ecf20Sopenharmony_ci close(STAT); 1438c2ecf20Sopenharmony_ci } 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci if ($statline eq '') { 1468c2ecf20Sopenharmony_ci $statline = "-1 (UNKNOWN_PROCESS_NAME) R 0"; 1478c2ecf20Sopenharmony_ci } 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci return $statline; 1508c2ecf20Sopenharmony_ci} 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cisub guess_process_pid($$) { 1538c2ecf20Sopenharmony_ci my $pid = $_[0]; 1548c2ecf20Sopenharmony_ci my $statline = $_[1]; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci if ($pid == 0) { 1578c2ecf20Sopenharmony_ci return "swapper-0"; 1588c2ecf20Sopenharmony_ci } 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci if ($statline !~ /$regex_statname/o) { 1618c2ecf20Sopenharmony_ci die("Failed to math stat line for process name :: $statline"); 1628c2ecf20Sopenharmony_ci } 1638c2ecf20Sopenharmony_ci return "$1-$pid"; 1648c2ecf20Sopenharmony_ci} 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_cisub parent_info($$) { 1678c2ecf20Sopenharmony_ci my $pid = $_[0]; 1688c2ecf20Sopenharmony_ci my $statline = $_[1]; 1698c2ecf20Sopenharmony_ci my $ppid; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci if ($pid == 0) { 1728c2ecf20Sopenharmony_ci return "NOPARENT-0"; 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci if ($statline !~ /$regex_statppid/o) { 1768c2ecf20Sopenharmony_ci die("Failed to match stat line process ppid:: $statline"); 1778c2ecf20Sopenharmony_ci } 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci # Read the ppid stat line 1808c2ecf20Sopenharmony_ci $ppid = $1; 1818c2ecf20Sopenharmony_ci return guess_process_pid($ppid, read_statline($ppid)); 1828c2ecf20Sopenharmony_ci} 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_cisub process_events { 1858c2ecf20Sopenharmony_ci my $traceevent; 1868c2ecf20Sopenharmony_ci my $process_pid; 1878c2ecf20Sopenharmony_ci my $cpus; 1888c2ecf20Sopenharmony_ci my $timestamp; 1898c2ecf20Sopenharmony_ci my $tracepoint; 1908c2ecf20Sopenharmony_ci my $details; 1918c2ecf20Sopenharmony_ci my $statline; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci # Read each line of the event log 1948c2ecf20Sopenharmony_ciEVENT_PROCESS: 1958c2ecf20Sopenharmony_ci while ($traceevent = <STDIN>) { 1968c2ecf20Sopenharmony_ci if ($traceevent =~ /$regex_traceevent/o) { 1978c2ecf20Sopenharmony_ci $process_pid = $1; 1988c2ecf20Sopenharmony_ci $tracepoint = $4; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci if ($opt_read_procstat || $opt_prepend_parent) { 2018c2ecf20Sopenharmony_ci $process_pid =~ /(.*)-([0-9]*)$/; 2028c2ecf20Sopenharmony_ci my $process = $1; 2038c2ecf20Sopenharmony_ci my $pid = $2; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci $statline = read_statline($pid); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci if ($opt_read_procstat && $process eq '') { 2088c2ecf20Sopenharmony_ci $process_pid = guess_process_pid($pid, $statline); 2098c2ecf20Sopenharmony_ci } 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci if ($opt_prepend_parent) { 2128c2ecf20Sopenharmony_ci $process_pid = parent_info($pid, $statline) . " :: $process_pid"; 2138c2ecf20Sopenharmony_ci } 2148c2ecf20Sopenharmony_ci } 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci # Unnecessary in this script. Uncomment if required 2178c2ecf20Sopenharmony_ci # $cpus = $2; 2188c2ecf20Sopenharmony_ci # $timestamp = $3; 2198c2ecf20Sopenharmony_ci } else { 2208c2ecf20Sopenharmony_ci next; 2218c2ecf20Sopenharmony_ci } 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci # Perl Switch() sucks majorly 2248c2ecf20Sopenharmony_ci if ($tracepoint eq "mm_page_alloc") { 2258c2ecf20Sopenharmony_ci $perprocesspid{$process_pid}->{MM_PAGE_ALLOC}++; 2268c2ecf20Sopenharmony_ci } elsif ($tracepoint eq "mm_page_free") { 2278c2ecf20Sopenharmony_ci $perprocesspid{$process_pid}->{MM_PAGE_FREE}++ 2288c2ecf20Sopenharmony_ci } elsif ($tracepoint eq "mm_page_free_batched") { 2298c2ecf20Sopenharmony_ci $perprocesspid{$process_pid}->{MM_PAGE_FREE_BATCHED}++; 2308c2ecf20Sopenharmony_ci } elsif ($tracepoint eq "mm_page_pcpu_drain") { 2318c2ecf20Sopenharmony_ci $perprocesspid{$process_pid}->{MM_PAGE_PCPU_DRAIN}++; 2328c2ecf20Sopenharmony_ci $perprocesspid{$process_pid}->{STATE_PCPU_PAGES_DRAINED}++; 2338c2ecf20Sopenharmony_ci } elsif ($tracepoint eq "mm_page_alloc_zone_locked") { 2348c2ecf20Sopenharmony_ci $perprocesspid{$process_pid}->{MM_PAGE_ALLOC_ZONE_LOCKED}++; 2358c2ecf20Sopenharmony_ci $perprocesspid{$process_pid}->{STATE_PCPU_PAGES_REFILLED}++; 2368c2ecf20Sopenharmony_ci } elsif ($tracepoint eq "mm_page_alloc_extfrag") { 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci # Extract the details of the event now 2398c2ecf20Sopenharmony_ci $details = $5; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci my ($page, $pfn); 2428c2ecf20Sopenharmony_ci my ($alloc_order, $fallback_order, $pageblock_order); 2438c2ecf20Sopenharmony_ci my ($alloc_migratetype, $fallback_migratetype); 2448c2ecf20Sopenharmony_ci my ($fragmenting, $change_ownership); 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci if ($details !~ /$regex_fragdetails/o) { 2478c2ecf20Sopenharmony_ci print "WARNING: Failed to parse mm_page_alloc_extfrag as expected\n"; 2488c2ecf20Sopenharmony_ci next; 2498c2ecf20Sopenharmony_ci } 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci $perprocesspid{$process_pid}->{MM_PAGE_ALLOC_EXTFRAG}++; 2528c2ecf20Sopenharmony_ci $page = $1; 2538c2ecf20Sopenharmony_ci $pfn = $2; 2548c2ecf20Sopenharmony_ci $alloc_order = $3; 2558c2ecf20Sopenharmony_ci $fallback_order = $4; 2568c2ecf20Sopenharmony_ci $pageblock_order = $5; 2578c2ecf20Sopenharmony_ci $alloc_migratetype = $6; 2588c2ecf20Sopenharmony_ci $fallback_migratetype = $7; 2598c2ecf20Sopenharmony_ci $fragmenting = $8; 2608c2ecf20Sopenharmony_ci $change_ownership = $9; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci if ($fragmenting) { 2638c2ecf20Sopenharmony_ci $perprocesspid{$process_pid}->{HIGH_EXT_FRAG}++; 2648c2ecf20Sopenharmony_ci if ($fallback_order <= 3) { 2658c2ecf20Sopenharmony_ci $perprocesspid{$process_pid}->{HIGH_EXT_FRAGMENT_SEVERE}++; 2668c2ecf20Sopenharmony_ci } else { 2678c2ecf20Sopenharmony_ci $perprocesspid{$process_pid}->{HIGH_EXT_FRAGMENT_MODERATE}++; 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci } 2708c2ecf20Sopenharmony_ci if ($change_ownership) { 2718c2ecf20Sopenharmony_ci $perprocesspid{$process_pid}->{HIGH_EXT_FRAGMENT_CHANGED}++; 2728c2ecf20Sopenharmony_ci } 2738c2ecf20Sopenharmony_ci } else { 2748c2ecf20Sopenharmony_ci $perprocesspid{$process_pid}->{EVENT_UNKNOWN}++; 2758c2ecf20Sopenharmony_ci } 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci # Catch a full pcpu drain event 2788c2ecf20Sopenharmony_ci if ($perprocesspid{$process_pid}->{STATE_PCPU_PAGES_DRAINED} && 2798c2ecf20Sopenharmony_ci $tracepoint ne "mm_page_pcpu_drain") { 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci $perprocesspid{$process_pid}->{HIGH_PCPU_DRAINS}++; 2828c2ecf20Sopenharmony_ci $perprocesspid{$process_pid}->{STATE_PCPU_PAGES_DRAINED} = 0; 2838c2ecf20Sopenharmony_ci } 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci # Catch a full pcpu refill event 2868c2ecf20Sopenharmony_ci if ($perprocesspid{$process_pid}->{STATE_PCPU_PAGES_REFILLED} && 2878c2ecf20Sopenharmony_ci $tracepoint ne "mm_page_alloc_zone_locked") { 2888c2ecf20Sopenharmony_ci $perprocesspid{$process_pid}->{HIGH_PCPU_REFILLS}++; 2898c2ecf20Sopenharmony_ci $perprocesspid{$process_pid}->{STATE_PCPU_PAGES_REFILLED} = 0; 2908c2ecf20Sopenharmony_ci } 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci if ($sigint_pending) { 2938c2ecf20Sopenharmony_ci last EVENT_PROCESS; 2948c2ecf20Sopenharmony_ci } 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci} 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cisub dump_stats { 2998c2ecf20Sopenharmony_ci my $hashref = shift; 3008c2ecf20Sopenharmony_ci my %stats = %$hashref; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci # Dump per-process stats 3038c2ecf20Sopenharmony_ci my $process_pid; 3048c2ecf20Sopenharmony_ci my $max_strlen = 0; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci # Get the maximum process name 3078c2ecf20Sopenharmony_ci foreach $process_pid (keys %perprocesspid) { 3088c2ecf20Sopenharmony_ci my $len = length($process_pid); 3098c2ecf20Sopenharmony_ci if ($len > $max_strlen) { 3108c2ecf20Sopenharmony_ci $max_strlen = $len; 3118c2ecf20Sopenharmony_ci } 3128c2ecf20Sopenharmony_ci } 3138c2ecf20Sopenharmony_ci $max_strlen += 2; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci printf("\n"); 3168c2ecf20Sopenharmony_ci printf("%-" . $max_strlen . "s %8s %10s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s\n", 3178c2ecf20Sopenharmony_ci "Process", "Pages", "Pages", "Pages", "Pages", "PCPU", "PCPU", "PCPU", "Fragment", "Fragment", "MigType", "Fragment", "Fragment", "Unknown"); 3188c2ecf20Sopenharmony_ci printf("%-" . $max_strlen . "s %8s %10s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s\n", 3198c2ecf20Sopenharmony_ci "details", "allocd", "allocd", "freed", "freed", "pages", "drains", "refills", "Fallback", "Causing", "Changed", "Severe", "Moderate", ""); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci printf("%-" . $max_strlen . "s %8s %10s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s\n", 3228c2ecf20Sopenharmony_ci "", "", "under lock", "direct", "pagevec", "drain", "", "", "", "", "", "", "", ""); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci foreach $process_pid (keys %stats) { 3258c2ecf20Sopenharmony_ci # Dump final aggregates 3268c2ecf20Sopenharmony_ci if ($stats{$process_pid}->{STATE_PCPU_PAGES_DRAINED}) { 3278c2ecf20Sopenharmony_ci $stats{$process_pid}->{HIGH_PCPU_DRAINS}++; 3288c2ecf20Sopenharmony_ci $stats{$process_pid}->{STATE_PCPU_PAGES_DRAINED} = 0; 3298c2ecf20Sopenharmony_ci } 3308c2ecf20Sopenharmony_ci if ($stats{$process_pid}->{STATE_PCPU_PAGES_REFILLED}) { 3318c2ecf20Sopenharmony_ci $stats{$process_pid}->{HIGH_PCPU_REFILLS}++; 3328c2ecf20Sopenharmony_ci $stats{$process_pid}->{STATE_PCPU_PAGES_REFILLED} = 0; 3338c2ecf20Sopenharmony_ci } 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci printf("%-" . $max_strlen . "s %8d %10d %8d %8d %8d %8d %8d %8d %8d %8d %8d %8d %8d\n", 3368c2ecf20Sopenharmony_ci $process_pid, 3378c2ecf20Sopenharmony_ci $stats{$process_pid}->{MM_PAGE_ALLOC}, 3388c2ecf20Sopenharmony_ci $stats{$process_pid}->{MM_PAGE_ALLOC_ZONE_LOCKED}, 3398c2ecf20Sopenharmony_ci $stats{$process_pid}->{MM_PAGE_FREE}, 3408c2ecf20Sopenharmony_ci $stats{$process_pid}->{MM_PAGE_FREE_BATCHED}, 3418c2ecf20Sopenharmony_ci $stats{$process_pid}->{MM_PAGE_PCPU_DRAIN}, 3428c2ecf20Sopenharmony_ci $stats{$process_pid}->{HIGH_PCPU_DRAINS}, 3438c2ecf20Sopenharmony_ci $stats{$process_pid}->{HIGH_PCPU_REFILLS}, 3448c2ecf20Sopenharmony_ci $stats{$process_pid}->{MM_PAGE_ALLOC_EXTFRAG}, 3458c2ecf20Sopenharmony_ci $stats{$process_pid}->{HIGH_EXT_FRAG}, 3468c2ecf20Sopenharmony_ci $stats{$process_pid}->{HIGH_EXT_FRAGMENT_CHANGED}, 3478c2ecf20Sopenharmony_ci $stats{$process_pid}->{HIGH_EXT_FRAGMENT_SEVERE}, 3488c2ecf20Sopenharmony_ci $stats{$process_pid}->{HIGH_EXT_FRAGMENT_MODERATE}, 3498c2ecf20Sopenharmony_ci $stats{$process_pid}->{EVENT_UNKNOWN}); 3508c2ecf20Sopenharmony_ci } 3518c2ecf20Sopenharmony_ci} 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_cisub aggregate_perprocesspid() { 3548c2ecf20Sopenharmony_ci my $process_pid; 3558c2ecf20Sopenharmony_ci my $process; 3568c2ecf20Sopenharmony_ci undef %perprocess; 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci foreach $process_pid (keys %perprocesspid) { 3598c2ecf20Sopenharmony_ci $process = $process_pid; 3608c2ecf20Sopenharmony_ci $process =~ s/-([0-9])*$//; 3618c2ecf20Sopenharmony_ci if ($process eq '') { 3628c2ecf20Sopenharmony_ci $process = "NO_PROCESS_NAME"; 3638c2ecf20Sopenharmony_ci } 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci $perprocess{$process}->{MM_PAGE_ALLOC} += $perprocesspid{$process_pid}->{MM_PAGE_ALLOC}; 3668c2ecf20Sopenharmony_ci $perprocess{$process}->{MM_PAGE_ALLOC_ZONE_LOCKED} += $perprocesspid{$process_pid}->{MM_PAGE_ALLOC_ZONE_LOCKED}; 3678c2ecf20Sopenharmony_ci $perprocess{$process}->{MM_PAGE_FREE} += $perprocesspid{$process_pid}->{MM_PAGE_FREE}; 3688c2ecf20Sopenharmony_ci $perprocess{$process}->{MM_PAGE_FREE_BATCHED} += $perprocesspid{$process_pid}->{MM_PAGE_FREE_BATCHED}; 3698c2ecf20Sopenharmony_ci $perprocess{$process}->{MM_PAGE_PCPU_DRAIN} += $perprocesspid{$process_pid}->{MM_PAGE_PCPU_DRAIN}; 3708c2ecf20Sopenharmony_ci $perprocess{$process}->{HIGH_PCPU_DRAINS} += $perprocesspid{$process_pid}->{HIGH_PCPU_DRAINS}; 3718c2ecf20Sopenharmony_ci $perprocess{$process}->{HIGH_PCPU_REFILLS} += $perprocesspid{$process_pid}->{HIGH_PCPU_REFILLS}; 3728c2ecf20Sopenharmony_ci $perprocess{$process}->{MM_PAGE_ALLOC_EXTFRAG} += $perprocesspid{$process_pid}->{MM_PAGE_ALLOC_EXTFRAG}; 3738c2ecf20Sopenharmony_ci $perprocess{$process}->{HIGH_EXT_FRAG} += $perprocesspid{$process_pid}->{HIGH_EXT_FRAG}; 3748c2ecf20Sopenharmony_ci $perprocess{$process}->{HIGH_EXT_FRAGMENT_CHANGED} += $perprocesspid{$process_pid}->{HIGH_EXT_FRAGMENT_CHANGED}; 3758c2ecf20Sopenharmony_ci $perprocess{$process}->{HIGH_EXT_FRAGMENT_SEVERE} += $perprocesspid{$process_pid}->{HIGH_EXT_FRAGMENT_SEVERE}; 3768c2ecf20Sopenharmony_ci $perprocess{$process}->{HIGH_EXT_FRAGMENT_MODERATE} += $perprocesspid{$process_pid}->{HIGH_EXT_FRAGMENT_MODERATE}; 3778c2ecf20Sopenharmony_ci $perprocess{$process}->{EVENT_UNKNOWN} += $perprocesspid{$process_pid}->{EVENT_UNKNOWN}; 3788c2ecf20Sopenharmony_ci } 3798c2ecf20Sopenharmony_ci} 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_cisub report() { 3828c2ecf20Sopenharmony_ci if (!$opt_ignorepid) { 3838c2ecf20Sopenharmony_ci dump_stats(\%perprocesspid); 3848c2ecf20Sopenharmony_ci } else { 3858c2ecf20Sopenharmony_ci aggregate_perprocesspid(); 3868c2ecf20Sopenharmony_ci dump_stats(\%perprocess); 3878c2ecf20Sopenharmony_ci } 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci# Process events or signals until neither is available 3918c2ecf20Sopenharmony_cisub signal_loop() { 3928c2ecf20Sopenharmony_ci my $sigint_processed; 3938c2ecf20Sopenharmony_ci do { 3948c2ecf20Sopenharmony_ci $sigint_processed = 0; 3958c2ecf20Sopenharmony_ci process_events(); 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci # Handle pending signals if any 3988c2ecf20Sopenharmony_ci if ($sigint_pending) { 3998c2ecf20Sopenharmony_ci my $current_time = time; 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci if ($sigint_exit) { 4028c2ecf20Sopenharmony_ci print "Received exit signal\n"; 4038c2ecf20Sopenharmony_ci $sigint_pending = 0; 4048c2ecf20Sopenharmony_ci } 4058c2ecf20Sopenharmony_ci if ($sigint_report) { 4068c2ecf20Sopenharmony_ci if ($current_time >= $sigint_received + 2) { 4078c2ecf20Sopenharmony_ci report(); 4088c2ecf20Sopenharmony_ci $sigint_report = 0; 4098c2ecf20Sopenharmony_ci $sigint_pending = 0; 4108c2ecf20Sopenharmony_ci $sigint_processed = 1; 4118c2ecf20Sopenharmony_ci } 4128c2ecf20Sopenharmony_ci } 4138c2ecf20Sopenharmony_ci } 4148c2ecf20Sopenharmony_ci } while ($sigint_pending || $sigint_processed); 4158c2ecf20Sopenharmony_ci} 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_cisignal_loop(); 4188c2ecf20Sopenharmony_cireport(); 419