-
Notifications
You must be signed in to change notification settings - Fork 40
/
tlbstat
executable file
·127 lines (120 loc) · 4.04 KB
/
tlbstat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#!/bin/bash
#
# tlbstat - measure and summarize TLBs. Uses Linux perf and PMCs.
#
# FROM: https://github.com/brendangregg/pmc-cloud-tools
#
# TLB: Translation Lookaside Buffer (the MMU page translation cache)
# PMC: Performance Monitoring Counters
#
# USAGE: tlbstat {-C CPU | -p PID | -c CMD} [interval [duration]]
#
# REQUIREMENTS: perf command, TLB PMCs (counters listed below) which may
# only be provided by Linux 4.14-ish and newer.
#
# Columns:
#
# - K_CYCLES: CPU Cycles x 1000
# - K_INSTR: CPU Instructions x 1000
# - IPC: Instructions-Per-Cycle
# - DTLB_WALKS: Data TLB walks (count)
# - ITLB_WALKS: Instruction TLB walks (count)
# - K_DTLBCYC: Cycles at least one PMH is active with data TLB walks x 1000
# - K_ITLBCYC: Cycles at least one PMH is active with instr. TLB walks x 1000
# - DTLB%: Data TLB active cycles as a ratio of total cycles
# - ITLB%: Instruction TLB active cycles as a ratio of total cycles
#
# Copyright 2018 Netflix, Inc.
# Licensed under the Apache License, Version 2.0 (the "License")
#
# 08-Jan-2018 Brendan Gregg Created this.
function usage {
cat <<-END >&2
USAGE: tlbstat {-C CPU | -p PID | -c CMD} [interval [duration]]
-C CPU # measure this CPU only
-p PID # measure this PID only
-c 'CMD' # measure this command only (quote it)
interval # output interval in secs (default 1)
duration # total seconds (default infinityish)
eg,
tlbstat # show stats across all CPUs
tlbstat 5 # show stats every 5 seconds
tlbstat -C 0 # measure CPU 0 only
tlbstat -p 181 # measure PID 181 only
tlbstat -c 'cksum /boot/*' # measure run and measure this cmd
END
exit
}
opt_cpu=0; opt_pid=0; opt_cmd=0; cpu=""; pid=""; cmd=""
while getopts C:p:c:h opt
do
case $opt in
C) opt_cpu=1; cpu=$OPTARG ;;
p) opt_pid=1; pid=$OPTARG ;;
c) opt_cmd=1; cmd=$OPTARG ;;
h|?) usage ;;
esac
done
shift $(( $OPTIND - 1 ))
if (( opt_cpu + opt_pid + opt_cmd > 1 )); then
echo >&2 "ERROR: pick one of -C, -p, -c"
usage
fi
secs=${1-1} # default 1 second
duration=${2-999999999} # default semi-infinite seconds
hlines=25 # lines to repeat header
target=-a
(( opt_cpu )) && target="-C $cpu sleep $duration"
(( opt_pid )) && target="-p $pid sleep $duration"
(( opt_cmd )) && target="$cmd"
if (( opt_pid )); then
if [ ! -d /proc/$pid ]; then
echo >&2 "ERROR: Can't find PID $pid. Exiting."
exit
fi
fi
# note that instructions is last on purpose, it triggers output
# cycles are twice as a workaround for an issue
perf stat -e cycles -e cycles \
-e dtlb_load_misses.miss_causes_a_walk \
-e dtlb_store_misses.miss_causes_a_walk \
-e itlb_misses.miss_causes_a_walk \
-e dtlb_load_misses.walk_active \
-e dtlb_store_misses.walk_active \
-e itlb_misses.walk_active \
-e instructions \
-I $(( secs * 1000 )) $target 2>&1 | awk -v hlines=$hlines '
BEGIN {
htxt = sprintf("%-10s %-10s %5s %-10s %-10s %-10s %-10s %5s %5s",
"K_CYCLES", "K_INSTR", "IPC", "DTLB_WALKS", "ITLB_WALKS",
"K_DTLBCYC", "K_ITLBCYC", "DTLB%", "ITLB%");
print htxt
header = hlines
}
/invalid/ { print $0 } # unsupported event
{ gsub(/,/, ""); }
$3 == "cycles" { cycles = $2; }
# counts:
$3 == "dtlb_load_misses.miss_causes_a_walk" { dtlbl = $2; }
$3 == "dtlb_store_misses.miss_causes_a_walk" { dtlbs = $2; }
$3 == "itlb_misses.miss_causes_a_walk" { itlb = $2; }
# walk active cycles in at least one PMH cycles:
$3 == "dtlb_load_misses.walk_active" { dtlblwc = $2; }
$3 == "dtlb_store_misses.walk_active" { dtlbswc = $2; }
$3 == "itlb_misses.walk_active" { itlbwc = $2; }
$3 == "instructions" {
if (--header == 0) {
print htxt
header = hlines
}
ins = $2
if (cycles == 0) { cycles = 1 } # PMCs are broken, or no events
printf("%-10d %-10d %5.2f %-10d %-10d %-10d %-10d %5.2f %5.2f\n",
cycles / 1000, ins / 1000, ins / cycles,
dtlbl + dtlbs, itlb,
(dtlblwc + dtlbswc) / 1000,
itlbwc / 1000,
100 * (dtlblwc + dtlbswc) / cycles,
100 * (itlbwc) / cycles)
}
'