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