xref: /OK3568_Linux_fs/kernel/Documentation/trace/postprocess/trace-vmscan-postprocess.pl (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#!/usr/bin/env perl
2*4882a593Smuzhiyun# This is a POC for reading the text representation of trace output related to
3*4882a593Smuzhiyun# page reclaim. It makes an attempt to extract some high-level information on
4*4882a593Smuzhiyun# what is going on. The accuracy of the parser may vary
5*4882a593Smuzhiyun#
6*4882a593Smuzhiyun# Example usage: trace-vmscan-postprocess.pl < /sys/kernel/debug/tracing/trace_pipe
7*4882a593Smuzhiyun# other options
8*4882a593Smuzhiyun#   --read-procstat	If the trace lacks process info, get it from /proc
9*4882a593Smuzhiyun#   --ignore-pid	Aggregate processes of the same name together
10*4882a593Smuzhiyun#
11*4882a593Smuzhiyun# Copyright (c) IBM Corporation 2009
12*4882a593Smuzhiyun# Author: Mel Gorman <mel@csn.ul.ie>
13*4882a593Smuzhiyunuse strict;
14*4882a593Smuzhiyunuse Getopt::Long;
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun# Tracepoint events
17*4882a593Smuzhiyunuse constant MM_VMSCAN_DIRECT_RECLAIM_BEGIN	=> 1;
18*4882a593Smuzhiyunuse constant MM_VMSCAN_DIRECT_RECLAIM_END	=> 2;
19*4882a593Smuzhiyunuse constant MM_VMSCAN_KSWAPD_WAKE		=> 3;
20*4882a593Smuzhiyunuse constant MM_VMSCAN_KSWAPD_SLEEP		=> 4;
21*4882a593Smuzhiyunuse constant MM_VMSCAN_LRU_SHRINK_ACTIVE	=> 5;
22*4882a593Smuzhiyunuse constant MM_VMSCAN_LRU_SHRINK_INACTIVE	=> 6;
23*4882a593Smuzhiyunuse constant MM_VMSCAN_LRU_ISOLATE		=> 7;
24*4882a593Smuzhiyunuse constant MM_VMSCAN_WRITEPAGE_FILE_SYNC	=> 8;
25*4882a593Smuzhiyunuse constant MM_VMSCAN_WRITEPAGE_ANON_SYNC	=> 9;
26*4882a593Smuzhiyunuse constant MM_VMSCAN_WRITEPAGE_FILE_ASYNC	=> 10;
27*4882a593Smuzhiyunuse constant MM_VMSCAN_WRITEPAGE_ANON_ASYNC	=> 11;
28*4882a593Smuzhiyunuse constant MM_VMSCAN_WRITEPAGE_ASYNC		=> 12;
29*4882a593Smuzhiyunuse constant EVENT_UNKNOWN			=> 13;
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun# Per-order events
32*4882a593Smuzhiyunuse constant MM_VMSCAN_DIRECT_RECLAIM_BEGIN_PERORDER => 11;
33*4882a593Smuzhiyunuse constant MM_VMSCAN_WAKEUP_KSWAPD_PERORDER 	=> 12;
34*4882a593Smuzhiyunuse constant MM_VMSCAN_KSWAPD_WAKE_PERORDER	=> 13;
35*4882a593Smuzhiyunuse constant HIGH_KSWAPD_REWAKEUP_PERORDER	=> 14;
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun# Constants used to track state
38*4882a593Smuzhiyunuse constant STATE_DIRECT_BEGIN 		=> 15;
39*4882a593Smuzhiyunuse constant STATE_DIRECT_ORDER 		=> 16;
40*4882a593Smuzhiyunuse constant STATE_KSWAPD_BEGIN			=> 17;
41*4882a593Smuzhiyunuse constant STATE_KSWAPD_ORDER			=> 18;
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun# High-level events extrapolated from tracepoints
44*4882a593Smuzhiyunuse constant HIGH_DIRECT_RECLAIM_LATENCY	=> 19;
45*4882a593Smuzhiyunuse constant HIGH_KSWAPD_LATENCY		=> 20;
46*4882a593Smuzhiyunuse constant HIGH_KSWAPD_REWAKEUP		=> 21;
47*4882a593Smuzhiyunuse constant HIGH_NR_SCANNED			=> 22;
48*4882a593Smuzhiyunuse constant HIGH_NR_TAKEN			=> 23;
49*4882a593Smuzhiyunuse constant HIGH_NR_RECLAIMED			=> 24;
50*4882a593Smuzhiyunuse constant HIGH_NR_FILE_SCANNED		=> 25;
51*4882a593Smuzhiyunuse constant HIGH_NR_ANON_SCANNED		=> 26;
52*4882a593Smuzhiyunuse constant HIGH_NR_FILE_RECLAIMED		=> 27;
53*4882a593Smuzhiyunuse constant HIGH_NR_ANON_RECLAIMED		=> 28;
54*4882a593Smuzhiyun
55*4882a593Smuzhiyunmy %perprocesspid;
56*4882a593Smuzhiyunmy %perprocess;
57*4882a593Smuzhiyunmy %last_procmap;
58*4882a593Smuzhiyunmy $opt_ignorepid;
59*4882a593Smuzhiyunmy $opt_read_procstat;
60*4882a593Smuzhiyun
61*4882a593Smuzhiyunmy $total_wakeup_kswapd;
62*4882a593Smuzhiyunmy ($total_direct_reclaim, $total_direct_nr_scanned);
63*4882a593Smuzhiyunmy ($total_direct_nr_file_scanned, $total_direct_nr_anon_scanned);
64*4882a593Smuzhiyunmy ($total_direct_latency, $total_kswapd_latency);
65*4882a593Smuzhiyunmy ($total_direct_nr_reclaimed);
66*4882a593Smuzhiyunmy ($total_direct_nr_file_reclaimed, $total_direct_nr_anon_reclaimed);
67*4882a593Smuzhiyunmy ($total_direct_writepage_file_sync, $total_direct_writepage_file_async);
68*4882a593Smuzhiyunmy ($total_direct_writepage_anon_sync, $total_direct_writepage_anon_async);
69*4882a593Smuzhiyunmy ($total_kswapd_nr_scanned, $total_kswapd_wake);
70*4882a593Smuzhiyunmy ($total_kswapd_nr_file_scanned, $total_kswapd_nr_anon_scanned);
71*4882a593Smuzhiyunmy ($total_kswapd_writepage_file_sync, $total_kswapd_writepage_file_async);
72*4882a593Smuzhiyunmy ($total_kswapd_writepage_anon_sync, $total_kswapd_writepage_anon_async);
73*4882a593Smuzhiyunmy ($total_kswapd_nr_reclaimed);
74*4882a593Smuzhiyunmy ($total_kswapd_nr_file_reclaimed, $total_kswapd_nr_anon_reclaimed);
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun# Catch sigint and exit on request
77*4882a593Smuzhiyunmy $sigint_report = 0;
78*4882a593Smuzhiyunmy $sigint_exit = 0;
79*4882a593Smuzhiyunmy $sigint_pending = 0;
80*4882a593Smuzhiyunmy $sigint_received = 0;
81*4882a593Smuzhiyunsub sigint_handler {
82*4882a593Smuzhiyun	my $current_time = time;
83*4882a593Smuzhiyun	if ($current_time - 2 > $sigint_received) {
84*4882a593Smuzhiyun		print "SIGINT received, report pending. Hit ctrl-c again to exit\n";
85*4882a593Smuzhiyun		$sigint_report = 1;
86*4882a593Smuzhiyun	} else {
87*4882a593Smuzhiyun		if (!$sigint_exit) {
88*4882a593Smuzhiyun			print "Second SIGINT received quickly, exiting\n";
89*4882a593Smuzhiyun		}
90*4882a593Smuzhiyun		$sigint_exit++;
91*4882a593Smuzhiyun	}
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun	if ($sigint_exit > 3) {
94*4882a593Smuzhiyun		print "Many SIGINTs received, exiting now without report\n";
95*4882a593Smuzhiyun		exit;
96*4882a593Smuzhiyun	}
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun	$sigint_received = $current_time;
99*4882a593Smuzhiyun	$sigint_pending = 1;
100*4882a593Smuzhiyun}
101*4882a593Smuzhiyun$SIG{INT} = "sigint_handler";
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun# Parse command line options
104*4882a593SmuzhiyunGetOptions(
105*4882a593Smuzhiyun	'ignore-pid'	 =>	\$opt_ignorepid,
106*4882a593Smuzhiyun	'read-procstat'	 =>	\$opt_read_procstat,
107*4882a593Smuzhiyun);
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun# Defaults for dynamically discovered regex's
110*4882a593Smuzhiyunmy $regex_direct_begin_default = 'order=([0-9]*) may_writepage=([0-9]*) gfp_flags=([A-Z_|]*)';
111*4882a593Smuzhiyunmy $regex_direct_end_default = 'nr_reclaimed=([0-9]*)';
112*4882a593Smuzhiyunmy $regex_kswapd_wake_default = 'nid=([0-9]*) order=([0-9]*)';
113*4882a593Smuzhiyunmy $regex_kswapd_sleep_default = 'nid=([0-9]*)';
114*4882a593Smuzhiyunmy $regex_wakeup_kswapd_default = 'nid=([0-9]*) zid=([0-9]*) order=([0-9]*) gfp_flags=([A-Z_|]*)';
115*4882a593Smuzhiyunmy $regex_lru_isolate_default = 'isolate_mode=([0-9]*) classzone_idx=([0-9]*) order=([0-9]*) nr_requested=([0-9]*) nr_scanned=([0-9]*) nr_skipped=([0-9]*) nr_taken=([0-9]*) lru=([a-z_]*)';
116*4882a593Smuzhiyunmy $regex_lru_shrink_inactive_default = 'nid=([0-9]*) nr_scanned=([0-9]*) nr_reclaimed=([0-9]*) nr_dirty=([0-9]*) nr_writeback=([0-9]*) nr_congested=([0-9]*) nr_immediate=([0-9]*) nr_activate_anon=([0-9]*) nr_activate_file=([0-9]*) nr_ref_keep=([0-9]*) nr_unmap_fail=([0-9]*) priority=([0-9]*) flags=([A-Z_|]*)';
117*4882a593Smuzhiyunmy $regex_lru_shrink_active_default = 'lru=([A-Z_]*) nr_scanned=([0-9]*) nr_rotated=([0-9]*) priority=([0-9]*)';
118*4882a593Smuzhiyunmy $regex_writepage_default = 'page=([0-9a-f]*) pfn=([0-9]*) flags=([A-Z_|]*)';
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun# Dyanically discovered regex
121*4882a593Smuzhiyunmy $regex_direct_begin;
122*4882a593Smuzhiyunmy $regex_direct_end;
123*4882a593Smuzhiyunmy $regex_kswapd_wake;
124*4882a593Smuzhiyunmy $regex_kswapd_sleep;
125*4882a593Smuzhiyunmy $regex_wakeup_kswapd;
126*4882a593Smuzhiyunmy $regex_lru_isolate;
127*4882a593Smuzhiyunmy $regex_lru_shrink_inactive;
128*4882a593Smuzhiyunmy $regex_lru_shrink_active;
129*4882a593Smuzhiyunmy $regex_writepage;
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun# Static regex used. Specified like this for readability and for use with /o
132*4882a593Smuzhiyun#                      (process_pid)     (cpus      )   ( time  )   (tpoint    ) (details)
133*4882a593Smuzhiyunmy $regex_traceevent = '\s*([a-zA-Z0-9-]*)\s*(\[[0-9]*\])(\s*[dX.][Nnp.][Hhs.][0-9a-fA-F.]*|)\s*([0-9.]*):\s*([a-zA-Z_]*):\s*(.*)';
134*4882a593Smuzhiyunmy $regex_statname = '[-0-9]*\s\((.*)\).*';
135*4882a593Smuzhiyunmy $regex_statppid = '[-0-9]*\s\(.*\)\s[A-Za-z]\s([0-9]*).*';
136*4882a593Smuzhiyun
137*4882a593Smuzhiyunsub generate_traceevent_regex {
138*4882a593Smuzhiyun	my $event = shift;
139*4882a593Smuzhiyun	my $default = shift;
140*4882a593Smuzhiyun	my $regex;
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun	# Read the event format or use the default
143*4882a593Smuzhiyun	if (!open (FORMAT, "/sys/kernel/debug/tracing/events/$event/format")) {
144*4882a593Smuzhiyun		print("WARNING: Event $event format string not found\n");
145*4882a593Smuzhiyun		return $default;
146*4882a593Smuzhiyun	} else {
147*4882a593Smuzhiyun		my $line;
148*4882a593Smuzhiyun		while (!eof(FORMAT)) {
149*4882a593Smuzhiyun			$line = <FORMAT>;
150*4882a593Smuzhiyun			$line =~ s/, REC->.*//;
151*4882a593Smuzhiyun			if ($line =~ /^print fmt:\s"(.*)".*/) {
152*4882a593Smuzhiyun				$regex = $1;
153*4882a593Smuzhiyun				$regex =~ s/%s/\([0-9a-zA-Z|_]*\)/g;
154*4882a593Smuzhiyun				$regex =~ s/%p/\([0-9a-f]*\)/g;
155*4882a593Smuzhiyun				$regex =~ s/%d/\([-0-9]*\)/g;
156*4882a593Smuzhiyun				$regex =~ s/%ld/\([-0-9]*\)/g;
157*4882a593Smuzhiyun				$regex =~ s/%lu/\([0-9]*\)/g;
158*4882a593Smuzhiyun			}
159*4882a593Smuzhiyun		}
160*4882a593Smuzhiyun	}
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun	# Can't handle the print_flags stuff but in the context of this
163*4882a593Smuzhiyun	# script, it really doesn't matter
164*4882a593Smuzhiyun	$regex =~ s/\(REC.*\) \? __print_flags.*//;
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun	# Verify fields are in the right order
167*4882a593Smuzhiyun	my $tuple;
168*4882a593Smuzhiyun	foreach $tuple (split /\s/, $regex) {
169*4882a593Smuzhiyun		my ($key, $value) = split(/=/, $tuple);
170*4882a593Smuzhiyun		my $expected = shift;
171*4882a593Smuzhiyun		if ($key ne $expected) {
172*4882a593Smuzhiyun			print("WARNING: Format not as expected for event $event '$key' != '$expected'\n");
173*4882a593Smuzhiyun			$regex =~ s/$key=\((.*)\)/$key=$1/;
174*4882a593Smuzhiyun		}
175*4882a593Smuzhiyun	}
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun	if (defined shift) {
178*4882a593Smuzhiyun		die("Fewer fields than expected in format");
179*4882a593Smuzhiyun	}
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun	return $regex;
182*4882a593Smuzhiyun}
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun$regex_direct_begin = generate_traceevent_regex(
185*4882a593Smuzhiyun			"vmscan/mm_vmscan_direct_reclaim_begin",
186*4882a593Smuzhiyun			$regex_direct_begin_default,
187*4882a593Smuzhiyun			"order", "may_writepage",
188*4882a593Smuzhiyun			"gfp_flags");
189*4882a593Smuzhiyun$regex_direct_end = generate_traceevent_regex(
190*4882a593Smuzhiyun			"vmscan/mm_vmscan_direct_reclaim_end",
191*4882a593Smuzhiyun			$regex_direct_end_default,
192*4882a593Smuzhiyun			"nr_reclaimed");
193*4882a593Smuzhiyun$regex_kswapd_wake = generate_traceevent_regex(
194*4882a593Smuzhiyun			"vmscan/mm_vmscan_kswapd_wake",
195*4882a593Smuzhiyun			$regex_kswapd_wake_default,
196*4882a593Smuzhiyun			"nid", "order");
197*4882a593Smuzhiyun$regex_kswapd_sleep = generate_traceevent_regex(
198*4882a593Smuzhiyun			"vmscan/mm_vmscan_kswapd_sleep",
199*4882a593Smuzhiyun			$regex_kswapd_sleep_default,
200*4882a593Smuzhiyun			"nid");
201*4882a593Smuzhiyun$regex_wakeup_kswapd = generate_traceevent_regex(
202*4882a593Smuzhiyun			"vmscan/mm_vmscan_wakeup_kswapd",
203*4882a593Smuzhiyun			$regex_wakeup_kswapd_default,
204*4882a593Smuzhiyun			"nid", "zid", "order", "gfp_flags");
205*4882a593Smuzhiyun$regex_lru_isolate = generate_traceevent_regex(
206*4882a593Smuzhiyun			"vmscan/mm_vmscan_lru_isolate",
207*4882a593Smuzhiyun			$regex_lru_isolate_default,
208*4882a593Smuzhiyun			"isolate_mode", "classzone_idx", "order",
209*4882a593Smuzhiyun			"nr_requested", "nr_scanned", "nr_skipped", "nr_taken",
210*4882a593Smuzhiyun			"lru");
211*4882a593Smuzhiyun$regex_lru_shrink_inactive = generate_traceevent_regex(
212*4882a593Smuzhiyun			"vmscan/mm_vmscan_lru_shrink_inactive",
213*4882a593Smuzhiyun			$regex_lru_shrink_inactive_default,
214*4882a593Smuzhiyun			"nid", "nr_scanned", "nr_reclaimed", "nr_dirty", "nr_writeback",
215*4882a593Smuzhiyun			"nr_congested", "nr_immediate", "nr_activate_anon",
216*4882a593Smuzhiyun			"nr_activate_file", "nr_ref_keep",
217*4882a593Smuzhiyun			"nr_unmap_fail", "priority", "flags");
218*4882a593Smuzhiyun$regex_lru_shrink_active = generate_traceevent_regex(
219*4882a593Smuzhiyun			"vmscan/mm_vmscan_lru_shrink_active",
220*4882a593Smuzhiyun			$regex_lru_shrink_active_default,
221*4882a593Smuzhiyun			"nid", "zid",
222*4882a593Smuzhiyun			"lru",
223*4882a593Smuzhiyun			"nr_scanned", "nr_rotated", "priority");
224*4882a593Smuzhiyun$regex_writepage = generate_traceevent_regex(
225*4882a593Smuzhiyun			"vmscan/mm_vmscan_writepage",
226*4882a593Smuzhiyun			$regex_writepage_default,
227*4882a593Smuzhiyun			"page", "pfn", "flags");
228*4882a593Smuzhiyun
229*4882a593Smuzhiyunsub read_statline($) {
230*4882a593Smuzhiyun	my $pid = $_[0];
231*4882a593Smuzhiyun	my $statline;
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun	if (open(STAT, "/proc/$pid/stat")) {
234*4882a593Smuzhiyun		$statline = <STAT>;
235*4882a593Smuzhiyun		close(STAT);
236*4882a593Smuzhiyun	}
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun	if ($statline eq '') {
239*4882a593Smuzhiyun		$statline = "-1 (UNKNOWN_PROCESS_NAME) R 0";
240*4882a593Smuzhiyun	}
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun	return $statline;
243*4882a593Smuzhiyun}
244*4882a593Smuzhiyun
245*4882a593Smuzhiyunsub guess_process_pid($$) {
246*4882a593Smuzhiyun	my $pid = $_[0];
247*4882a593Smuzhiyun	my $statline = $_[1];
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun	if ($pid == 0) {
250*4882a593Smuzhiyun		return "swapper-0";
251*4882a593Smuzhiyun	}
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun	if ($statline !~ /$regex_statname/o) {
254*4882a593Smuzhiyun		die("Failed to math stat line for process name :: $statline");
255*4882a593Smuzhiyun	}
256*4882a593Smuzhiyun	return "$1-$pid";
257*4882a593Smuzhiyun}
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun# Convert sec.usec timestamp format
260*4882a593Smuzhiyunsub timestamp_to_ms($) {
261*4882a593Smuzhiyun	my $timestamp = $_[0];
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun	my ($sec, $usec) = split (/\./, $timestamp);
264*4882a593Smuzhiyun	return ($sec * 1000) + ($usec / 1000);
265*4882a593Smuzhiyun}
266*4882a593Smuzhiyun
267*4882a593Smuzhiyunsub process_events {
268*4882a593Smuzhiyun	my $traceevent;
269*4882a593Smuzhiyun	my $process_pid;
270*4882a593Smuzhiyun	my $cpus;
271*4882a593Smuzhiyun	my $timestamp;
272*4882a593Smuzhiyun	my $tracepoint;
273*4882a593Smuzhiyun	my $details;
274*4882a593Smuzhiyun	my $statline;
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun	# Read each line of the event log
277*4882a593SmuzhiyunEVENT_PROCESS:
278*4882a593Smuzhiyun	while ($traceevent = <STDIN>) {
279*4882a593Smuzhiyun		if ($traceevent =~ /$regex_traceevent/o) {
280*4882a593Smuzhiyun			$process_pid = $1;
281*4882a593Smuzhiyun			$timestamp = $4;
282*4882a593Smuzhiyun			$tracepoint = $5;
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun			$process_pid =~ /(.*)-([0-9]*)$/;
285*4882a593Smuzhiyun			my $process = $1;
286*4882a593Smuzhiyun			my $pid = $2;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun			if ($process eq "") {
289*4882a593Smuzhiyun				$process = $last_procmap{$pid};
290*4882a593Smuzhiyun				$process_pid = "$process-$pid";
291*4882a593Smuzhiyun			}
292*4882a593Smuzhiyun			$last_procmap{$pid} = $process;
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun			if ($opt_read_procstat) {
295*4882a593Smuzhiyun				$statline = read_statline($pid);
296*4882a593Smuzhiyun				if ($opt_read_procstat && $process eq '') {
297*4882a593Smuzhiyun					$process_pid = guess_process_pid($pid, $statline);
298*4882a593Smuzhiyun				}
299*4882a593Smuzhiyun			}
300*4882a593Smuzhiyun		} else {
301*4882a593Smuzhiyun			next;
302*4882a593Smuzhiyun		}
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun		# Perl Switch() sucks majorly
305*4882a593Smuzhiyun		if ($tracepoint eq "mm_vmscan_direct_reclaim_begin") {
306*4882a593Smuzhiyun			$timestamp = timestamp_to_ms($timestamp);
307*4882a593Smuzhiyun			$perprocesspid{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN}++;
308*4882a593Smuzhiyun			$perprocesspid{$process_pid}->{STATE_DIRECT_BEGIN} = $timestamp;
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun			$details = $6;
311*4882a593Smuzhiyun			if ($details !~ /$regex_direct_begin/o) {
312*4882a593Smuzhiyun				print "WARNING: Failed to parse mm_vmscan_direct_reclaim_begin as expected\n";
313*4882a593Smuzhiyun				print "         $details\n";
314*4882a593Smuzhiyun				print "         $regex_direct_begin\n";
315*4882a593Smuzhiyun				next;
316*4882a593Smuzhiyun			}
317*4882a593Smuzhiyun			my $order = $1;
318*4882a593Smuzhiyun			$perprocesspid{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN_PERORDER}[$order]++;
319*4882a593Smuzhiyun			$perprocesspid{$process_pid}->{STATE_DIRECT_ORDER} = $order;
320*4882a593Smuzhiyun		} elsif ($tracepoint eq "mm_vmscan_direct_reclaim_end") {
321*4882a593Smuzhiyun			# Count the event itself
322*4882a593Smuzhiyun			my $index = $perprocesspid{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_END};
323*4882a593Smuzhiyun			$perprocesspid{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_END}++;
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun			# Record how long direct reclaim took this time
326*4882a593Smuzhiyun			if (defined $perprocesspid{$process_pid}->{STATE_DIRECT_BEGIN}) {
327*4882a593Smuzhiyun				$timestamp = timestamp_to_ms($timestamp);
328*4882a593Smuzhiyun				my $order = $perprocesspid{$process_pid}->{STATE_DIRECT_ORDER};
329*4882a593Smuzhiyun				my $latency = ($timestamp - $perprocesspid{$process_pid}->{STATE_DIRECT_BEGIN});
330*4882a593Smuzhiyun				$perprocesspid{$process_pid}->{HIGH_DIRECT_RECLAIM_LATENCY}[$index] = "$order-$latency";
331*4882a593Smuzhiyun			}
332*4882a593Smuzhiyun		} elsif ($tracepoint eq "mm_vmscan_kswapd_wake") {
333*4882a593Smuzhiyun			$details = $6;
334*4882a593Smuzhiyun			if ($details !~ /$regex_kswapd_wake/o) {
335*4882a593Smuzhiyun				print "WARNING: Failed to parse mm_vmscan_kswapd_wake as expected\n";
336*4882a593Smuzhiyun				print "         $details\n";
337*4882a593Smuzhiyun				print "         $regex_kswapd_wake\n";
338*4882a593Smuzhiyun				next;
339*4882a593Smuzhiyun			}
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun			my $order = $2;
342*4882a593Smuzhiyun			$perprocesspid{$process_pid}->{STATE_KSWAPD_ORDER} = $order;
343*4882a593Smuzhiyun			if (!$perprocesspid{$process_pid}->{STATE_KSWAPD_BEGIN}) {
344*4882a593Smuzhiyun				$timestamp = timestamp_to_ms($timestamp);
345*4882a593Smuzhiyun				$perprocesspid{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE}++;
346*4882a593Smuzhiyun				$perprocesspid{$process_pid}->{STATE_KSWAPD_BEGIN} = $timestamp;
347*4882a593Smuzhiyun				$perprocesspid{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE_PERORDER}[$order]++;
348*4882a593Smuzhiyun			} else {
349*4882a593Smuzhiyun				$perprocesspid{$process_pid}->{HIGH_KSWAPD_REWAKEUP}++;
350*4882a593Smuzhiyun				$perprocesspid{$process_pid}->{HIGH_KSWAPD_REWAKEUP_PERORDER}[$order]++;
351*4882a593Smuzhiyun			}
352*4882a593Smuzhiyun		} elsif ($tracepoint eq "mm_vmscan_kswapd_sleep") {
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun			# Count the event itself
355*4882a593Smuzhiyun			my $index = $perprocesspid{$process_pid}->{MM_VMSCAN_KSWAPD_SLEEP};
356*4882a593Smuzhiyun			$perprocesspid{$process_pid}->{MM_VMSCAN_KSWAPD_SLEEP}++;
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun			# Record how long kswapd was awake
359*4882a593Smuzhiyun			$timestamp = timestamp_to_ms($timestamp);
360*4882a593Smuzhiyun			my $order = $perprocesspid{$process_pid}->{STATE_KSWAPD_ORDER};
361*4882a593Smuzhiyun			my $latency = ($timestamp - $perprocesspid{$process_pid}->{STATE_KSWAPD_BEGIN});
362*4882a593Smuzhiyun			$perprocesspid{$process_pid}->{HIGH_KSWAPD_LATENCY}[$index] = "$order-$latency";
363*4882a593Smuzhiyun			$perprocesspid{$process_pid}->{STATE_KSWAPD_BEGIN} = 0;
364*4882a593Smuzhiyun		} elsif ($tracepoint eq "mm_vmscan_wakeup_kswapd") {
365*4882a593Smuzhiyun			$perprocesspid{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD}++;
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun			$details = $6;
368*4882a593Smuzhiyun			if ($details !~ /$regex_wakeup_kswapd/o) {
369*4882a593Smuzhiyun				print "WARNING: Failed to parse mm_vmscan_wakeup_kswapd as expected\n";
370*4882a593Smuzhiyun				print "         $details\n";
371*4882a593Smuzhiyun				print "         $regex_wakeup_kswapd\n";
372*4882a593Smuzhiyun				next;
373*4882a593Smuzhiyun			}
374*4882a593Smuzhiyun			my $order = $3;
375*4882a593Smuzhiyun			$perprocesspid{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD_PERORDER}[$order]++;
376*4882a593Smuzhiyun		} elsif ($tracepoint eq "mm_vmscan_lru_isolate") {
377*4882a593Smuzhiyun			$details = $6;
378*4882a593Smuzhiyun			if ($details !~ /$regex_lru_isolate/o) {
379*4882a593Smuzhiyun				print "WARNING: Failed to parse mm_vmscan_lru_isolate as expected\n";
380*4882a593Smuzhiyun				print "         $details\n";
381*4882a593Smuzhiyun				print "         $regex_lru_isolate/o\n";
382*4882a593Smuzhiyun				next;
383*4882a593Smuzhiyun			}
384*4882a593Smuzhiyun			my $isolate_mode = $1;
385*4882a593Smuzhiyun			my $nr_scanned = $5;
386*4882a593Smuzhiyun			my $file = $8;
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun			# To closer match vmstat scanning statistics, only count isolate_both
389*4882a593Smuzhiyun			# and isolate_inactive as scanning. isolate_active is rotation
390*4882a593Smuzhiyun			# isolate_inactive == 1
391*4882a593Smuzhiyun			# isolate_active   == 2
392*4882a593Smuzhiyun			# isolate_both     == 3
393*4882a593Smuzhiyun			if ($isolate_mode != 2) {
394*4882a593Smuzhiyun				$perprocesspid{$process_pid}->{HIGH_NR_SCANNED} += $nr_scanned;
395*4882a593Smuzhiyun				if ($file =~ /_file/) {
396*4882a593Smuzhiyun					$perprocesspid{$process_pid}->{HIGH_NR_FILE_SCANNED} += $nr_scanned;
397*4882a593Smuzhiyun				} else {
398*4882a593Smuzhiyun					$perprocesspid{$process_pid}->{HIGH_NR_ANON_SCANNED} += $nr_scanned;
399*4882a593Smuzhiyun				}
400*4882a593Smuzhiyun			}
401*4882a593Smuzhiyun		} elsif ($tracepoint eq "mm_vmscan_lru_shrink_inactive") {
402*4882a593Smuzhiyun			$details = $6;
403*4882a593Smuzhiyun			if ($details !~ /$regex_lru_shrink_inactive/o) {
404*4882a593Smuzhiyun				print "WARNING: Failed to parse mm_vmscan_lru_shrink_inactive as expected\n";
405*4882a593Smuzhiyun				print "         $details\n";
406*4882a593Smuzhiyun				print "         $regex_lru_shrink_inactive/o\n";
407*4882a593Smuzhiyun				next;
408*4882a593Smuzhiyun			}
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun			my $nr_reclaimed = $3;
411*4882a593Smuzhiyun			my $flags = $13;
412*4882a593Smuzhiyun			my $file = 0;
413*4882a593Smuzhiyun			if ($flags =~ /RECLAIM_WB_FILE/) {
414*4882a593Smuzhiyun				$file = 1;
415*4882a593Smuzhiyun			}
416*4882a593Smuzhiyun			$perprocesspid{$process_pid}->{HIGH_NR_RECLAIMED} += $nr_reclaimed;
417*4882a593Smuzhiyun			if ($file) {
418*4882a593Smuzhiyun				$perprocesspid{$process_pid}->{HIGH_NR_FILE_RECLAIMED} += $nr_reclaimed;
419*4882a593Smuzhiyun			} else {
420*4882a593Smuzhiyun				$perprocesspid{$process_pid}->{HIGH_NR_ANON_RECLAIMED} += $nr_reclaimed;
421*4882a593Smuzhiyun			}
422*4882a593Smuzhiyun		} elsif ($tracepoint eq "mm_vmscan_writepage") {
423*4882a593Smuzhiyun			$details = $6;
424*4882a593Smuzhiyun			if ($details !~ /$regex_writepage/o) {
425*4882a593Smuzhiyun				print "WARNING: Failed to parse mm_vmscan_writepage as expected\n";
426*4882a593Smuzhiyun				print "         $details\n";
427*4882a593Smuzhiyun				print "         $regex_writepage\n";
428*4882a593Smuzhiyun				next;
429*4882a593Smuzhiyun			}
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun			my $flags = $3;
432*4882a593Smuzhiyun			my $file = 0;
433*4882a593Smuzhiyun			my $sync_io = 0;
434*4882a593Smuzhiyun			if ($flags =~ /RECLAIM_WB_FILE/) {
435*4882a593Smuzhiyun				$file = 1;
436*4882a593Smuzhiyun			}
437*4882a593Smuzhiyun			if ($flags =~ /RECLAIM_WB_SYNC/) {
438*4882a593Smuzhiyun				$sync_io = 1;
439*4882a593Smuzhiyun			}
440*4882a593Smuzhiyun			if ($sync_io) {
441*4882a593Smuzhiyun				if ($file) {
442*4882a593Smuzhiyun					$perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC}++;
443*4882a593Smuzhiyun				} else {
444*4882a593Smuzhiyun					$perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC}++;
445*4882a593Smuzhiyun				}
446*4882a593Smuzhiyun			} else {
447*4882a593Smuzhiyun				if ($file) {
448*4882a593Smuzhiyun					$perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC}++;
449*4882a593Smuzhiyun				} else {
450*4882a593Smuzhiyun					$perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_ASYNC}++;
451*4882a593Smuzhiyun				}
452*4882a593Smuzhiyun			}
453*4882a593Smuzhiyun		} else {
454*4882a593Smuzhiyun			$perprocesspid{$process_pid}->{EVENT_UNKNOWN}++;
455*4882a593Smuzhiyun		}
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun		if ($sigint_pending) {
458*4882a593Smuzhiyun			last EVENT_PROCESS;
459*4882a593Smuzhiyun		}
460*4882a593Smuzhiyun	}
461*4882a593Smuzhiyun}
462*4882a593Smuzhiyun
463*4882a593Smuzhiyunsub dump_stats {
464*4882a593Smuzhiyun	my $hashref = shift;
465*4882a593Smuzhiyun	my %stats = %$hashref;
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun	# Dump per-process stats
468*4882a593Smuzhiyun	my $process_pid;
469*4882a593Smuzhiyun	my $max_strlen = 0;
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun	# Get the maximum process name
472*4882a593Smuzhiyun	foreach $process_pid (keys %perprocesspid) {
473*4882a593Smuzhiyun		my $len = length($process_pid);
474*4882a593Smuzhiyun		if ($len > $max_strlen) {
475*4882a593Smuzhiyun			$max_strlen = $len;
476*4882a593Smuzhiyun		}
477*4882a593Smuzhiyun	}
478*4882a593Smuzhiyun	$max_strlen += 2;
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun	# Work out latencies
481*4882a593Smuzhiyun	printf("\n") if !$opt_ignorepid;
482*4882a593Smuzhiyun	printf("Reclaim latencies expressed as order-latency_in_ms\n") if !$opt_ignorepid;
483*4882a593Smuzhiyun	foreach $process_pid (keys %stats) {
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun		if (!$stats{$process_pid}->{HIGH_DIRECT_RECLAIM_LATENCY}[0] &&
486*4882a593Smuzhiyun				!$stats{$process_pid}->{HIGH_KSWAPD_LATENCY}[0]) {
487*4882a593Smuzhiyun			next;
488*4882a593Smuzhiyun		}
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun		printf "%-" . $max_strlen . "s ", $process_pid if !$opt_ignorepid;
491*4882a593Smuzhiyun		my $index = 0;
492*4882a593Smuzhiyun		while (defined $stats{$process_pid}->{HIGH_DIRECT_RECLAIM_LATENCY}[$index] ||
493*4882a593Smuzhiyun			defined $stats{$process_pid}->{HIGH_KSWAPD_LATENCY}[$index]) {
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun			if ($stats{$process_pid}->{HIGH_DIRECT_RECLAIM_LATENCY}[$index]) {
496*4882a593Smuzhiyun				printf("%s ", $stats{$process_pid}->{HIGH_DIRECT_RECLAIM_LATENCY}[$index]) if !$opt_ignorepid;
497*4882a593Smuzhiyun				my ($dummy, $latency) = split(/-/, $stats{$process_pid}->{HIGH_DIRECT_RECLAIM_LATENCY}[$index]);
498*4882a593Smuzhiyun				$total_direct_latency += $latency;
499*4882a593Smuzhiyun			} else {
500*4882a593Smuzhiyun				printf("%s ", $stats{$process_pid}->{HIGH_KSWAPD_LATENCY}[$index]) if !$opt_ignorepid;
501*4882a593Smuzhiyun				my ($dummy, $latency) = split(/-/, $stats{$process_pid}->{HIGH_KSWAPD_LATENCY}[$index]);
502*4882a593Smuzhiyun				$total_kswapd_latency += $latency;
503*4882a593Smuzhiyun			}
504*4882a593Smuzhiyun			$index++;
505*4882a593Smuzhiyun		}
506*4882a593Smuzhiyun		print "\n" if !$opt_ignorepid;
507*4882a593Smuzhiyun	}
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun	# Print out process activity
510*4882a593Smuzhiyun	printf("\n");
511*4882a593Smuzhiyun	printf("%-" . $max_strlen . "s %8s %10s   %8s %8s  %8s %8s %8s %8s\n", "Process", "Direct",  "Wokeup", "Pages",   "Pages",   "Pages",   "Pages",     "Time");
512*4882a593Smuzhiyun	printf("%-" . $max_strlen . "s %8s %10s   %8s %8s  %8s %8s %8s %8s\n", "details", "Rclms",   "Kswapd", "Scanned", "Rclmed",  "Sync-IO", "ASync-IO",  "Stalled");
513*4882a593Smuzhiyun	foreach $process_pid (keys %stats) {
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun		if (!$stats{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN}) {
516*4882a593Smuzhiyun			next;
517*4882a593Smuzhiyun		}
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun		$total_direct_reclaim += $stats{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN};
520*4882a593Smuzhiyun		$total_wakeup_kswapd += $stats{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD};
521*4882a593Smuzhiyun		$total_direct_nr_scanned += $stats{$process_pid}->{HIGH_NR_SCANNED};
522*4882a593Smuzhiyun		$total_direct_nr_file_scanned += $stats{$process_pid}->{HIGH_NR_FILE_SCANNED};
523*4882a593Smuzhiyun		$total_direct_nr_anon_scanned += $stats{$process_pid}->{HIGH_NR_ANON_SCANNED};
524*4882a593Smuzhiyun		$total_direct_nr_reclaimed += $stats{$process_pid}->{HIGH_NR_RECLAIMED};
525*4882a593Smuzhiyun		$total_direct_nr_file_reclaimed += $stats{$process_pid}->{HIGH_NR_FILE_RECLAIMED};
526*4882a593Smuzhiyun		$total_direct_nr_anon_reclaimed += $stats{$process_pid}->{HIGH_NR_ANON_RECLAIMED};
527*4882a593Smuzhiyun		$total_direct_writepage_file_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC};
528*4882a593Smuzhiyun		$total_direct_writepage_anon_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC};
529*4882a593Smuzhiyun		$total_direct_writepage_file_async += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC};
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun		$total_direct_writepage_anon_async += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_ASYNC};
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun		my $index = 0;
534*4882a593Smuzhiyun		my $this_reclaim_delay = 0;
535*4882a593Smuzhiyun		while (defined $stats{$process_pid}->{HIGH_DIRECT_RECLAIM_LATENCY}[$index]) {
536*4882a593Smuzhiyun			 my ($dummy, $latency) = split(/-/, $stats{$process_pid}->{HIGH_DIRECT_RECLAIM_LATENCY}[$index]);
537*4882a593Smuzhiyun			$this_reclaim_delay += $latency;
538*4882a593Smuzhiyun			$index++;
539*4882a593Smuzhiyun		}
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun		printf("%-" . $max_strlen . "s %8d %10d   %8u %8u  %8u %8u %8.3f",
542*4882a593Smuzhiyun			$process_pid,
543*4882a593Smuzhiyun			$stats{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN},
544*4882a593Smuzhiyun			$stats{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD},
545*4882a593Smuzhiyun			$stats{$process_pid}->{HIGH_NR_SCANNED},
546*4882a593Smuzhiyun			$stats{$process_pid}->{HIGH_NR_FILE_SCANNED},
547*4882a593Smuzhiyun			$stats{$process_pid}->{HIGH_NR_ANON_SCANNED},
548*4882a593Smuzhiyun			$stats{$process_pid}->{HIGH_NR_RECLAIMED},
549*4882a593Smuzhiyun			$stats{$process_pid}->{HIGH_NR_FILE_RECLAIMED},
550*4882a593Smuzhiyun			$stats{$process_pid}->{HIGH_NR_ANON_RECLAIMED},
551*4882a593Smuzhiyun			$stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC},
552*4882a593Smuzhiyun			$stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_ASYNC},
553*4882a593Smuzhiyun			$this_reclaim_delay / 1000);
554*4882a593Smuzhiyun
555*4882a593Smuzhiyun		if ($stats{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN}) {
556*4882a593Smuzhiyun			print "      ";
557*4882a593Smuzhiyun			for (my $order = 0; $order < 20; $order++) {
558*4882a593Smuzhiyun				my $count = $stats{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN_PERORDER}[$order];
559*4882a593Smuzhiyun				if ($count != 0) {
560*4882a593Smuzhiyun					print "direct-$order=$count ";
561*4882a593Smuzhiyun				}
562*4882a593Smuzhiyun			}
563*4882a593Smuzhiyun		}
564*4882a593Smuzhiyun		if ($stats{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD}) {
565*4882a593Smuzhiyun			print "      ";
566*4882a593Smuzhiyun			for (my $order = 0; $order < 20; $order++) {
567*4882a593Smuzhiyun				my $count = $stats{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD_PERORDER}[$order];
568*4882a593Smuzhiyun				if ($count != 0) {
569*4882a593Smuzhiyun					print "wakeup-$order=$count ";
570*4882a593Smuzhiyun				}
571*4882a593Smuzhiyun			}
572*4882a593Smuzhiyun		}
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun		print "\n";
575*4882a593Smuzhiyun	}
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun	# Print out kswapd activity
578*4882a593Smuzhiyun	printf("\n");
579*4882a593Smuzhiyun	printf("%-" . $max_strlen . "s %8s %10s   %8s   %8s %8s %8s\n", "Kswapd",   "Kswapd",  "Order",     "Pages",   "Pages",   "Pages",  "Pages");
580*4882a593Smuzhiyun	printf("%-" . $max_strlen . "s %8s %10s   %8s   %8s %8s %8s\n", "Instance", "Wakeups", "Re-wakeup", "Scanned", "Rclmed",  "Sync-IO", "ASync-IO");
581*4882a593Smuzhiyun	foreach $process_pid (keys %stats) {
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun		if (!$stats{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE}) {
584*4882a593Smuzhiyun			next;
585*4882a593Smuzhiyun		}
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun		$total_kswapd_wake += $stats{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE};
588*4882a593Smuzhiyun		$total_kswapd_nr_scanned += $stats{$process_pid}->{HIGH_NR_SCANNED};
589*4882a593Smuzhiyun		$total_kswapd_nr_file_scanned += $stats{$process_pid}->{HIGH_NR_FILE_SCANNED};
590*4882a593Smuzhiyun		$total_kswapd_nr_anon_scanned += $stats{$process_pid}->{HIGH_NR_ANON_SCANNED};
591*4882a593Smuzhiyun		$total_kswapd_nr_reclaimed += $stats{$process_pid}->{HIGH_NR_RECLAIMED};
592*4882a593Smuzhiyun		$total_kswapd_nr_file_reclaimed += $stats{$process_pid}->{HIGH_NR_FILE_RECLAIMED};
593*4882a593Smuzhiyun		$total_kswapd_nr_anon_reclaimed += $stats{$process_pid}->{HIGH_NR_ANON_RECLAIMED};
594*4882a593Smuzhiyun		$total_kswapd_writepage_file_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC};
595*4882a593Smuzhiyun		$total_kswapd_writepage_anon_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC};
596*4882a593Smuzhiyun		$total_kswapd_writepage_file_async += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC};
597*4882a593Smuzhiyun		$total_kswapd_writepage_anon_async += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_ASYNC};
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun		printf("%-" . $max_strlen . "s %8d %10d   %8u %8u  %8i %8u",
600*4882a593Smuzhiyun			$process_pid,
601*4882a593Smuzhiyun			$stats{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE},
602*4882a593Smuzhiyun			$stats{$process_pid}->{HIGH_KSWAPD_REWAKEUP},
603*4882a593Smuzhiyun			$stats{$process_pid}->{HIGH_NR_SCANNED},
604*4882a593Smuzhiyun			$stats{$process_pid}->{HIGH_NR_FILE_SCANNED},
605*4882a593Smuzhiyun			$stats{$process_pid}->{HIGH_NR_ANON_SCANNED},
606*4882a593Smuzhiyun			$stats{$process_pid}->{HIGH_NR_RECLAIMED},
607*4882a593Smuzhiyun			$stats{$process_pid}->{HIGH_NR_FILE_RECLAIMED},
608*4882a593Smuzhiyun			$stats{$process_pid}->{HIGH_NR_ANON_RECLAIMED},
609*4882a593Smuzhiyun			$stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC},
610*4882a593Smuzhiyun			$stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_ASYNC});
611*4882a593Smuzhiyun
612*4882a593Smuzhiyun		if ($stats{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE}) {
613*4882a593Smuzhiyun			print "      ";
614*4882a593Smuzhiyun			for (my $order = 0; $order < 20; $order++) {
615*4882a593Smuzhiyun				my $count = $stats{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE_PERORDER}[$order];
616*4882a593Smuzhiyun				if ($count != 0) {
617*4882a593Smuzhiyun					print "wake-$order=$count ";
618*4882a593Smuzhiyun				}
619*4882a593Smuzhiyun			}
620*4882a593Smuzhiyun		}
621*4882a593Smuzhiyun		if ($stats{$process_pid}->{HIGH_KSWAPD_REWAKEUP}) {
622*4882a593Smuzhiyun			print "      ";
623*4882a593Smuzhiyun			for (my $order = 0; $order < 20; $order++) {
624*4882a593Smuzhiyun				my $count = $stats{$process_pid}->{HIGH_KSWAPD_REWAKEUP_PERORDER}[$order];
625*4882a593Smuzhiyun				if ($count != 0) {
626*4882a593Smuzhiyun					print "rewake-$order=$count ";
627*4882a593Smuzhiyun				}
628*4882a593Smuzhiyun			}
629*4882a593Smuzhiyun		}
630*4882a593Smuzhiyun		printf("\n");
631*4882a593Smuzhiyun	}
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun	# Print out summaries
634*4882a593Smuzhiyun	$total_direct_latency /= 1000;
635*4882a593Smuzhiyun	$total_kswapd_latency /= 1000;
636*4882a593Smuzhiyun	print "\nSummary\n";
637*4882a593Smuzhiyun	print "Direct reclaims:     			$total_direct_reclaim\n";
638*4882a593Smuzhiyun	print "Direct reclaim pages scanned:		$total_direct_nr_scanned\n";
639*4882a593Smuzhiyun	print "Direct reclaim file pages scanned:	$total_direct_nr_file_scanned\n";
640*4882a593Smuzhiyun	print "Direct reclaim anon pages scanned:	$total_direct_nr_anon_scanned\n";
641*4882a593Smuzhiyun	print "Direct reclaim pages reclaimed:		$total_direct_nr_reclaimed\n";
642*4882a593Smuzhiyun	print "Direct reclaim file pages reclaimed:	$total_direct_nr_file_reclaimed\n";
643*4882a593Smuzhiyun	print "Direct reclaim anon pages reclaimed:	$total_direct_nr_anon_reclaimed\n";
644*4882a593Smuzhiyun	print "Direct reclaim write file sync I/O:	$total_direct_writepage_file_sync\n";
645*4882a593Smuzhiyun	print "Direct reclaim write anon sync I/O:	$total_direct_writepage_anon_sync\n";
646*4882a593Smuzhiyun	print "Direct reclaim write file async I/O:	$total_direct_writepage_file_async\n";
647*4882a593Smuzhiyun	print "Direct reclaim write anon async I/O:	$total_direct_writepage_anon_async\n";
648*4882a593Smuzhiyun	print "Wake kswapd requests:			$total_wakeup_kswapd\n";
649*4882a593Smuzhiyun	printf "Time stalled direct reclaim: 		%-1.2f seconds\n", $total_direct_latency;
650*4882a593Smuzhiyun	print "\n";
651*4882a593Smuzhiyun	print "Kswapd wakeups:				$total_kswapd_wake\n";
652*4882a593Smuzhiyun	print "Kswapd pages scanned:			$total_kswapd_nr_scanned\n";
653*4882a593Smuzhiyun	print "Kswapd file pages scanned:		$total_kswapd_nr_file_scanned\n";
654*4882a593Smuzhiyun	print "Kswapd anon pages scanned:		$total_kswapd_nr_anon_scanned\n";
655*4882a593Smuzhiyun	print "Kswapd pages reclaimed:			$total_kswapd_nr_reclaimed\n";
656*4882a593Smuzhiyun	print "Kswapd file pages reclaimed:		$total_kswapd_nr_file_reclaimed\n";
657*4882a593Smuzhiyun	print "Kswapd anon pages reclaimed:		$total_kswapd_nr_anon_reclaimed\n";
658*4882a593Smuzhiyun	print "Kswapd reclaim write file sync I/O:	$total_kswapd_writepage_file_sync\n";
659*4882a593Smuzhiyun	print "Kswapd reclaim write anon sync I/O:	$total_kswapd_writepage_anon_sync\n";
660*4882a593Smuzhiyun	print "Kswapd reclaim write file async I/O:	$total_kswapd_writepage_file_async\n";
661*4882a593Smuzhiyun	print "Kswapd reclaim write anon async I/O:	$total_kswapd_writepage_anon_async\n";
662*4882a593Smuzhiyun	printf "Time kswapd awake:			%-1.2f seconds\n", $total_kswapd_latency;
663*4882a593Smuzhiyun}
664*4882a593Smuzhiyun
665*4882a593Smuzhiyunsub aggregate_perprocesspid() {
666*4882a593Smuzhiyun	my $process_pid;
667*4882a593Smuzhiyun	my $process;
668*4882a593Smuzhiyun	undef %perprocess;
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun	foreach $process_pid (keys %perprocesspid) {
671*4882a593Smuzhiyun		$process = $process_pid;
672*4882a593Smuzhiyun		$process =~ s/-([0-9])*$//;
673*4882a593Smuzhiyun		if ($process eq '') {
674*4882a593Smuzhiyun			$process = "NO_PROCESS_NAME";
675*4882a593Smuzhiyun		}
676*4882a593Smuzhiyun
677*4882a593Smuzhiyun		$perprocess{$process}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN} += $perprocesspid{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN};
678*4882a593Smuzhiyun		$perprocess{$process}->{MM_VMSCAN_KSWAPD_WAKE} += $perprocesspid{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE};
679*4882a593Smuzhiyun		$perprocess{$process}->{MM_VMSCAN_WAKEUP_KSWAPD} += $perprocesspid{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD};
680*4882a593Smuzhiyun		$perprocess{$process}->{HIGH_KSWAPD_REWAKEUP} += $perprocesspid{$process_pid}->{HIGH_KSWAPD_REWAKEUP};
681*4882a593Smuzhiyun		$perprocess{$process}->{HIGH_NR_SCANNED} += $perprocesspid{$process_pid}->{HIGH_NR_SCANNED};
682*4882a593Smuzhiyun		$perprocess{$process}->{HIGH_NR_FILE_SCANNED} += $perprocesspid{$process_pid}->{HIGH_NR_FILE_SCANNED};
683*4882a593Smuzhiyun		$perprocess{$process}->{HIGH_NR_ANON_SCANNED} += $perprocesspid{$process_pid}->{HIGH_NR_ANON_SCANNED};
684*4882a593Smuzhiyun		$perprocess{$process}->{HIGH_NR_RECLAIMED} += $perprocesspid{$process_pid}->{HIGH_NR_RECLAIMED};
685*4882a593Smuzhiyun		$perprocess{$process}->{HIGH_NR_FILE_RECLAIMED} += $perprocesspid{$process_pid}->{HIGH_NR_FILE_RECLAIMED};
686*4882a593Smuzhiyun		$perprocess{$process}->{HIGH_NR_ANON_RECLAIMED} += $perprocesspid{$process_pid}->{HIGH_NR_ANON_RECLAIMED};
687*4882a593Smuzhiyun		$perprocess{$process}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC} += $perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC};
688*4882a593Smuzhiyun		$perprocess{$process}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC} += $perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC};
689*4882a593Smuzhiyun		$perprocess{$process}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC} += $perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC};
690*4882a593Smuzhiyun		$perprocess{$process}->{MM_VMSCAN_WRITEPAGE_ANON_ASYNC} += $perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_ASYNC};
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun		for (my $order = 0; $order < 20; $order++) {
693*4882a593Smuzhiyun			$perprocess{$process}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN_PERORDER}[$order] += $perprocesspid{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN_PERORDER}[$order];
694*4882a593Smuzhiyun			$perprocess{$process}->{MM_VMSCAN_WAKEUP_KSWAPD_PERORDER}[$order] += $perprocesspid{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD_PERORDER}[$order];
695*4882a593Smuzhiyun			$perprocess{$process}->{MM_VMSCAN_KSWAPD_WAKE_PERORDER}[$order] += $perprocesspid{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE_PERORDER}[$order];
696*4882a593Smuzhiyun
697*4882a593Smuzhiyun		}
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun		# Aggregate direct reclaim latencies
700*4882a593Smuzhiyun		my $wr_index = $perprocess{$process}->{MM_VMSCAN_DIRECT_RECLAIM_END};
701*4882a593Smuzhiyun		my $rd_index = 0;
702*4882a593Smuzhiyun		while (defined $perprocesspid{$process_pid}->{HIGH_DIRECT_RECLAIM_LATENCY}[$rd_index]) {
703*4882a593Smuzhiyun			$perprocess{$process}->{HIGH_DIRECT_RECLAIM_LATENCY}[$wr_index] = $perprocesspid{$process_pid}->{HIGH_DIRECT_RECLAIM_LATENCY}[$rd_index];
704*4882a593Smuzhiyun			$rd_index++;
705*4882a593Smuzhiyun			$wr_index++;
706*4882a593Smuzhiyun		}
707*4882a593Smuzhiyun		$perprocess{$process}->{MM_VMSCAN_DIRECT_RECLAIM_END} = $wr_index;
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun		# Aggregate kswapd latencies
710*4882a593Smuzhiyun		my $wr_index = $perprocess{$process}->{MM_VMSCAN_KSWAPD_SLEEP};
711*4882a593Smuzhiyun		my $rd_index = 0;
712*4882a593Smuzhiyun		while (defined $perprocesspid{$process_pid}->{HIGH_KSWAPD_LATENCY}[$rd_index]) {
713*4882a593Smuzhiyun			$perprocess{$process}->{HIGH_KSWAPD_LATENCY}[$wr_index] = $perprocesspid{$process_pid}->{HIGH_KSWAPD_LATENCY}[$rd_index];
714*4882a593Smuzhiyun			$rd_index++;
715*4882a593Smuzhiyun			$wr_index++;
716*4882a593Smuzhiyun		}
717*4882a593Smuzhiyun		$perprocess{$process}->{MM_VMSCAN_DIRECT_RECLAIM_END} = $wr_index;
718*4882a593Smuzhiyun	}
719*4882a593Smuzhiyun}
720*4882a593Smuzhiyun
721*4882a593Smuzhiyunsub report() {
722*4882a593Smuzhiyun	if (!$opt_ignorepid) {
723*4882a593Smuzhiyun		dump_stats(\%perprocesspid);
724*4882a593Smuzhiyun	} else {
725*4882a593Smuzhiyun		aggregate_perprocesspid();
726*4882a593Smuzhiyun		dump_stats(\%perprocess);
727*4882a593Smuzhiyun	}
728*4882a593Smuzhiyun}
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun# Process events or signals until neither is available
731*4882a593Smuzhiyunsub signal_loop() {
732*4882a593Smuzhiyun	my $sigint_processed;
733*4882a593Smuzhiyun	do {
734*4882a593Smuzhiyun		$sigint_processed = 0;
735*4882a593Smuzhiyun		process_events();
736*4882a593Smuzhiyun
737*4882a593Smuzhiyun		# Handle pending signals if any
738*4882a593Smuzhiyun		if ($sigint_pending) {
739*4882a593Smuzhiyun			my $current_time = time;
740*4882a593Smuzhiyun
741*4882a593Smuzhiyun			if ($sigint_exit) {
742*4882a593Smuzhiyun				print "Received exit signal\n";
743*4882a593Smuzhiyun				$sigint_pending = 0;
744*4882a593Smuzhiyun			}
745*4882a593Smuzhiyun			if ($sigint_report) {
746*4882a593Smuzhiyun				if ($current_time >= $sigint_received + 2) {
747*4882a593Smuzhiyun					report();
748*4882a593Smuzhiyun					$sigint_report = 0;
749*4882a593Smuzhiyun					$sigint_pending = 0;
750*4882a593Smuzhiyun					$sigint_processed = 1;
751*4882a593Smuzhiyun				}
752*4882a593Smuzhiyun			}
753*4882a593Smuzhiyun		}
754*4882a593Smuzhiyun	} while ($sigint_pending || $sigint_processed);
755*4882a593Smuzhiyun}
756*4882a593Smuzhiyun
757*4882a593Smuzhiyunsignal_loop();
758*4882a593Smuzhiyunreport();
759