File process_vmstat.awk of Package mmdebug-tools
#!/usr/bin/awk -f
# Process output of read_vmstat tool
# Format
#
# TS SCANNING STATS RECLAIM STATS SUCC RATE (reclaim/scan) INVOCATIONS RECLAIM/ROTATION/REFILL/SWAPOUT (percentage wrt scan)
# RECLAIM ts: 1623960193 pgscan_kswapd 8288 pgscan_direct 12672 kswapd_steal 6827 direct_steal 7309 kswad_succ 82% direct_succ 57% pageoutrun 82 allocstall 124 reclaimed 14136 67% pgrotated 1103 5% pgrefill 7201 34% pswpout 5585 26%
#
# Allocation stats
# TS Page allocator Page faults
# ALLOC: ts:1623960188 pgalloc 50173 pgfree 58791 pgfault 110799 pgmajfault 12
#
# IO stats
# TS read IO write IO SWAP IN/OU Overall IMMEDIATE SWAPOUT/write IO
# IO ts: 1623960191 pgpgin 2624 pgpgout 14900 pswpin 0 pswpout 3725 pswpin/out 3% pswpout/pgpgout 25%
#
# LRU stats
# TS Free pages ANON/FILE LRUS Inactive/active Unevict SLABS Reclaim/unreclaim
# STATE ts: 1623960209 nr_free 70926 anon 7898603 0.11 file 58729 0.98 unevictable 0 slab 40217 1.01
#
# Trashing detection
# refaults_per - refaults wrt major faults (can be more than 100% due to readahead)
# *activation_per - activations per refault for the resp. lru
# *restore_per - restores per refaults for the resp lru
# REFAULT ts: 1655144526 refault_anon 2880 activate_anon 412 restore_anon 7 refault_file 556 activate_file 469 restore_file 154 refaults_per 116% anon_activations_per 0% file_activations_per 0% anon_restore_per 0% file_restore_per 0%
BEGIN { first=1}
/^=S/ {
ts=$2
}
/^E=/ {
# relative counters report diffs
if (!first) {
# Reclaim statistics
printf("RECLAIM ts: %s pgscan_kswapd %d pgscan_direct %d pgsteal_kswapd %d pgsteal_direct %d ", ts,
pgscan_kswapd, pgscan_direct, pgsteal_kswapd, pgsteal_direct);
direct_succ=kswapd_succ=0
if (pgscan_kswapd)
kswapd_succ=pgsteal_kswapd * 100 / pgscan_kswapd
if (pgscan_direct)
direct_succ=pgsteal_direct * 100 / pgscan_direct
printf("kswapd_succ %d%% direct_succ %d%% ",
kswapd_succ, direct_succ);
printf("pageoutrun %d allocstall %d direct_throttled %d oom_kill %d ",
pageoutrun, allocstall,
direct_throttled, oom_kill)
scanned=pgscan_kswapd+pgscan_direct
pgrotate_per = pgrefill_per = swapout_per = steal_per = 0;
if (scanned) {
pgrotate_per= pgrotate * 100 / scanned
pgrefill_per = pgrefill * 100 / scanned
swapout_per=pswpout * 100 / scanned
steal_per=(pgsteal_kswapd+pgsteal_direct) * 100 /scanned
}
reclaimed = pgsteal_kswapd + pgsteal_direct
printf("reclaimed %d %d%% pgrotated %d %d%% pgrefill %d %d%% pswpout %d %d%%\n",
reclaimed, steal_per,
pgrotated, pgrotate_per,
pgrefill, pgrefill_per,
pswpout, swapout_per);
# Allocation statistics
printf("ALLOC ts: %s pgalloc %d pgfree %d pgfault %d pgmajfault %d\n", ts,
pgalloc, pgfree, pgfault, pgmajfault)
# IO stats
printf("IO ts: %s pgpgin %d pgpgout %d pswpin %d pswpout %d ", ts,
pgpgin, pgpgout, pswpin, pswpout)
pswpout_per=pswpin_per=0
if (pgpgout)
pswpout_per=pswpout * 100 / pgpgout
if (pswpout)
pswpin_per=pswpin * 100 / pswpout
printf("pswpin/out %d%% pswpout/pgpgout %d%%\n",
pswpin_per, pswpout_per)
# Refault stats were more coarse in older kernels
printf ("REFAULT ts: %s ", ts)
if (refault_ver) {
printf("refault %d activate %d ", refault, activate)
# Proportion of refaults wrt major faults
refaults_per = 0
if (pgmajfault)
refaults_per = refault * 100 / pgmajfault
printf("refaults_per %d%% ", refaults_per)
activations_per = 0
if (refault)
activations_per = activations * 100 / refault
printf("activations_per %d%%\n", activations_per)
} else {
printf("refault_anon %d activate_anon %d restore_anon %d refault_file %d activate_file %d restore_file %d ",
refault_anon, activate_anon, restore_anon,
refault_file, activate_file, restore_file)
# Proportion of refaults wrt major faults
refaults_per = 0
if (pgmajfault)
refaults_per = (refault_anon + refault_file) * 100 / pgmajfault
printf("refaults_per %d%% ", refaults_per)
# Recent enough to activate
anon_activations_per = file_activations_per = 0
if (refault_anon)
anon_activations_per = anon_activations * 100 / refault_anon
if (refault_file)
file_activations_per = file_activations * 100 / refault_file
printf("anon_activations_per %d%% file_activations_per %d%% ",
anon_activations_per, file_activations_per)
# Workingset reclaimed
anon_restore_per = file_restore_per = 0
if (refault_anon)
anon_restore_per = anon_restore * 100 / refault_anon
if (refault_file)
file_restore_per = file_restore * 100 / refault_file
printf("anon_restore_per %d%% file_restore_per %d%%\n",
anon_restore_per, file_restore_per)
}
# Compaction stats
compact_succ_per = 0
if (compact_stall)
compact_succ_per = compact_success * 100 / compact_stall;
printf("COMPACT ts:%s compact_stall %d compact_fail %d compact_success %d %d%% free_scanned %d isolated %d ", ts,
compact_stall, compact_fail, compact_success, compact_succ_per,
compact_free_scanned, compact_isolated)
printf("daenon_wake %d daemon_migrate_scanned %d daemon_free_scanned\n",
compact_daemon_wake, compact_daemon_migrate_scanned, compact_daemon_free_scanned)
}
first=0
printf("STATE ts: %s nr_free %d anon %d %.2f file %d %.2f unevictable %d slab %d %.2f\n", ts,
nr_free_pages,
nr_active_anon+nr_inactive_anon, nr_inactive_anon/nr_active_anon,
nr_active_file+nr_inactive_file, nr_inactive_file/nr_active_file,
unevictable,
nr_slab_reclaimable+nr_slab_unreclaimable, nr_slab_reclaimable/nr_slab_unreclaimable)
}
/nr_free_pages/ {nr_free_pages=$2}
/nr_inactive_anon/ {nr_inactive_anon=$2}
/nr_active_anon/ {nr_active_anon=$2; if (nr_active_anon == 0) nr_active_anon = 1}
/nr_inactive_file/ {nr_inactive_file=$2}
/nr_active_file/ {nr_active_file=$2; if (nr_active_file == 0) nr_active_file = 1}
/nr_unevictable/ {nr_unevictable=$2}
/nr_slab_reclaimable/ {nr_slab_reclaimable=$2}
/nr_slab_unreclaimable/ {nr_slab_unreclaimable=$2}
/pgpgin/{
pgpgin=$2-last_pgpgin
last_pgpgin=$2
}
/pgpgout/{
pgpgout=$2-last_pgpgout
last_pgpgout=$2
}
/pswpin/{
pswpin=$2-last_pswpin
last_pswpin=$2
}
/pswpout/{
pswpout=$2-last_pswpout
last_pswpout=$2
}
/pgalloc_dma/{pgalloc_sum=0}
/pgalloc_dma32/{pgalloc_sum+=$2}
/pgalloc_normal/{
pgalloc_sum+=$2
pgalloc=pgalloc_sum-last_pgalloc
last_pgalloc=pgalloc_sum
}
/pgfree/{
pgfree=$2-last_pgfree
last_pgfree=$2
}
/pgfault/{
pgfault=$2-last_pgfault
last_pgfault=$2
}
/pgmajfault/{
pgmajfault=$2-last_pgmajfault
last_pgmajfault=$2
}
/pgrefill_dma/{pgrefill_sum=$2}
/pgrefill_dma32/{pgrefill_sum+=$2}
/pgrefill_normal/{
pgrefill_sum+=$2
pgrefill=pgrefill_sum-last_pgrefill
last_pgrefill=pgrefill_sum
}
# Older kernels didn't have per zone break down
/pgrefill/{
pgrefill=$2-last_pgrefill
last_pgrefill=$2
}
# kswapd + direct
/pgsteal_dma/{pgsteal_sum=$2}
/pgsteal_dma32/{pgsteal_sum+=$2}
/pgsteal_normal/{
pgsteal_sum+=$2
pgsteal=pgsteal_sum-last_pgsteal
last_pgsteal=pgsteal_sum
}
/pgscan_kswapd_dma/{pgscan_kswapd_sum=$2}
/pgscan_kswapd_dma32/{pgscan_kswapd_sum+=$2}
/pgscan_kswapd_normal/{
pgscan_kswapd_sum+=$2
pgscan_kswapd=pgscan_kswapd_sum-last_pgscan_kswapd
last_pgscan_kswapd=pgscan_kswapd_sum
}
/pgscan_direct_dma/{pgscan_direct_sum=$2}
/pgscan_direct_dma32/{pgscan_direct_sum+=$2}
/pgscan_direct_normal/{
pgscan_direct_sum+=$2
pgscan_direct=pgscan_direct_sum-last_pgscan_direct
last_pgscan_direct=pgscan_direct_sum
}
/kswapd_steal/{
pgsteal_kswapd=$2-last_kswapd_steal
pgsteal_direct=pgsteal-kswapd_steal
last_kswapd_steal=$2
}
# older kernels had separate pgsteal for kswapd and direct reclaim
/pgsteal_kswapd/{
pgsteal_kswapd = $2 - last_pgsteal_kswapd_diff;
last_pgsteal_kswapd_diff = $2;
}
/pgsteal_direct/{
pgsteal_direct = $2 - last_pgsteal_direct_diff;
last_pgsteal_direct_diff = $2;
}
/pgscan_kswapd\>/{
pgscan_kswapd=$2-last_pgscan_kswapd
last_pgscan_kswapd=$2
}
/pgscan_direct\>/{
pgscan_direct=$2-last_pgscan_direct
last_pgscan_direct=$2
}
/pageoutrun/ {
pageoutrun=$2-last_pageoutrun
last_pageoutrun=$2
}
# Old kernels have per zone allocstall
/allocstall_dma/{allocstall_sum=$2}
/allocstall_dma32/{allocstall_sum+=$2}
/allocstall_normal/{
allocstall_sum+=$2
allocstall=allocstall_sum-last_allocstall
last_allocstall=allocstall_sum
}
/allocstall\>/ {
diff=$2-last_allocstall
last_allocstall=$2
}
/pgrotated/ {
pgrotated=$2-last_pgrotated
last_pgrotated=$2
}
/pgscan_direct_throttle/{
direct_throttle=$2-last_direct_throttle
last_direct_throttle=$2
}
/oom_kill/{
oom_kill=$2-last_oom_kill
last_oom_kill=$2
}
/workingset_refault\>/{
refault_ver = 1
refault = $2 - last_refault;
last_refault=$2
}
/workingset_refault_anon/{
refault_anon = $2 - last_refault_anon;
last_refault_anon=$2
}
/workingset_refault_file/{
refault_file = $2 - last_refault_file;
last_refault_file=$2
}
/workingset_activate/{
activate = $2 - last_activate;
last_activate=$2
}
/workingset_activate_anon/{
activate_anon = $2 - last_activate_anon;
last_activate_anon=$2
}
/workingset_activate_file/{
activate_file = $2 - last_activate_file;
last_activate_file=$2
}
/workingset_restore_anon/{
restore_anon = $2 - last_restore_anon;
last_restore_anon=$2
}
/workingset_restore_file/{
restore_file = $2 - last_restore_file;
last_restore_file=$2
}
/compact_stall/{
compact_stall = $2 - last_compact_stall
last_compact_stall = $2
}
/compact_fail/{
compact_fail = $2 - last_compact_fail
last_compact_fail = $2
}
/compact_success/{
compact_success = $2 - last_compact_success
last_compact_success = $2
}
/compact_free_scanned/{
compact_free_scanned = $2 - last_compact_free_scanned
last_compact_free_scanned = $2
}
/compact_isolated/{
compact_isolated = $2 - last_compact_isolated
last_compact_isolated = $2
}
/compact_daemon_wake/{
compact_daemon_wake = $2 - last_compact_daemon_wake
last_compact_daemon_wake = $2
}
/compact_daemon_migrate_scanned/{
compact_daemon_migrate_scanned = $2 - last_compact_daemon_migrate_scanned
last_compact_daemon_migrate_scanned = $2
}
/compact_daemon_free_scanned/{
compact_daemon_free_scanned = $2 - last_compact_daemon_free_scanned
last_compact_daemon_free_scanned = $2
}