Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1#!/bin/bash
2# perf stat tests
3# SPDX-License-Identifier: GPL-2.0
4
5set -e
6
7err=0
8test_default_stat() {
9 echo "Basic stat command test"
10 if ! perf stat true 2>&1 | grep -E -q "Performance counter stats for 'true':"
11 then
12 echo "Basic stat command test [Failed]"
13 err=1
14 return
15 fi
16 echo "Basic stat command test [Success]"
17}
18
19test_null_stat() {
20 echo "Null stat command test"
21 if ! perf stat --null true 2>&1 | grep -E -q "Performance counter stats for 'true':"
22 then
23 echo "Null stat command test [Failed]"
24 err=1
25 return
26 fi
27 echo "Null stat command test [Success]"
28}
29
30find_offline_cpu() {
31 for i in $(seq 1 4096)
32 do
33 if [[ ! -f /sys/devices/system/cpu/cpu$i/online || \
34 $(cat /sys/devices/system/cpu/cpu$i/online) == "0" ]]
35 then
36 echo $i
37 return
38 fi
39 done
40 echo "Failed to find offline CPU"
41 exit 1
42}
43
44test_offline_cpu_stat() {
45 cpu=$(find_offline_cpu)
46 echo "Offline CPU stat command test (cpu $cpu)"
47 if ! perf stat "-C$cpu" -e cycles true 2>&1 | grep -E -q "No supported events found."
48 then
49 echo "Offline CPU stat command test [Failed]"
50 err=1
51 return
52 fi
53 echo "Offline CPU stat command test [Success]"
54}
55
56test_stat_record_report() {
57 echo "stat record and report test"
58 if ! perf stat record -e task-clock -o - true | perf stat report -i - 2>&1 | \
59 grep -E -q "Performance counter stats for 'pipe':"
60 then
61 echo "stat record and report test [Failed]"
62 err=1
63 return
64 fi
65 echo "stat record and report test [Success]"
66}
67
68test_stat_record_script() {
69 echo "stat record and script test"
70 if ! perf stat record -e task-clock -o - true | perf script -i - 2>&1 | \
71 grep -E -q "CPU[[:space:]]+THREAD[[:space:]]+VAL[[:space:]]+ENA[[:space:]]+RUN[[:space:]]+TIME[[:space:]]+EVENT"
72 then
73 echo "stat record and script test [Failed]"
74 err=1
75 return
76 fi
77 echo "stat record and script test [Success]"
78}
79
80test_stat_repeat_weak_groups() {
81 echo "stat repeat weak groups test"
82 if ! perf stat -e '{cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles}' \
83 true 2>&1 | grep -q 'seconds time elapsed'
84 then
85 echo "stat repeat weak groups test [Skipped event parsing failed]"
86 return
87 fi
88 if ! perf stat -r2 -e '{cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles}:W' \
89 true > /dev/null 2>&1
90 then
91 echo "stat repeat weak groups test [Failed]"
92 err=1
93 return
94 fi
95 echo "stat repeat weak groups test [Success]"
96}
97
98test_topdown_groups() {
99 # Topdown events must be grouped with the slots event first. Test that
100 # parse-events reorders this.
101 echo "Topdown event group test"
102 if ! perf stat -e '{slots,topdown-retiring}' true > /dev/null 2>&1
103 then
104 echo "Topdown event group test [Skipped event parsing failed]"
105 return
106 fi
107 td_err=0
108 do_topdown_group_test() {
109 events=$1
110 failure=$2
111 if perf stat -e "$events" true 2>&1 | grep -E -q "<not supported>"
112 then
113 echo "Topdown event group test [Failed $failure for '$events']"
114 td_err=1
115 return
116 fi
117 }
118 do_topdown_group_test "{slots,topdown-retiring}" "events not supported"
119 do_topdown_group_test "{instructions,r400,r8000}" "raw format slots not reordered first"
120 filler_events=("instructions" "cycles"
121 "context-switches" "faults")
122 for ((i = 0; i < ${#filler_events[@]}; i+=2))
123 do
124 filler1=${filler_events[i]}
125 filler2=${filler_events[i+1]}
126 do_topdown_group_test "$filler1,topdown-retiring,slots" \
127 "slots not reordered first in no-group case"
128 do_topdown_group_test "slots,$filler1,topdown-retiring" \
129 "topdown metrics event not reordered in no-group case"
130 do_topdown_group_test "{$filler1,topdown-retiring,slots}" \
131 "slots not reordered first in single group case"
132 do_topdown_group_test "{$filler1,slots},topdown-retiring" \
133 "topdown metrics event not move into slots group"
134 do_topdown_group_test "topdown-retiring,{$filler1,slots}" \
135 "topdown metrics event not move into slots group last"
136 do_topdown_group_test "{$filler1,slots},{topdown-retiring}" \
137 "topdown metrics group not merge into slots group"
138 do_topdown_group_test "{topdown-retiring},{$filler1,slots}" \
139 "topdown metrics group not merge into slots group last"
140 do_topdown_group_test "{$filler1,slots},$filler2,topdown-retiring" \
141 "non-adjacent topdown metrics group not move into slots group"
142 do_topdown_group_test "$filler2,topdown-retiring,{$filler1,slots}" \
143 "non-adjacent topdown metrics group not move into slots group last"
144 do_topdown_group_test "{$filler1,slots},{$filler2,topdown-retiring}" \
145 "metrics group not merge into slots group"
146 do_topdown_group_test "{$filler1,topdown-retiring},{$filler2,slots}" \
147 "metrics group not merge into slots group last"
148 done
149 if test "$td_err" -eq 0
150 then
151 echo "Topdown event group test [Success]"
152 else
153 err="$td_err"
154 fi
155}
156
157test_topdown_weak_groups() {
158 # Weak groups break if the perf_event_open of multiple grouped events
159 # fails. Breaking a topdown group causes the events to fail. Test a very large
160 # grouping to see that the topdown events aren't broken out.
161 echo "Topdown weak groups test"
162 ok_grouping="{slots,topdown-bad-spec,topdown-be-bound,topdown-fe-bound,topdown-retiring},branch-instructions,branch-misses,bus-cycles,cache-misses,cache-references,cpu-cycles,instructions,mem-loads,mem-stores,ref-cycles,cache-misses,cache-references"
163 if ! perf stat --no-merge -e "$ok_grouping" true > /dev/null 2>&1
164 then
165 echo "Topdown weak groups test [Skipped event parsing failed]"
166 return
167 fi
168 group_needs_break="{slots,topdown-bad-spec,topdown-be-bound,topdown-fe-bound,topdown-retiring,branch-instructions,branch-misses,bus-cycles,cache-misses,cache-references,cpu-cycles,instructions,mem-loads,mem-stores,ref-cycles,cache-misses,cache-references}:W"
169 if perf stat --no-merge -e "$group_needs_break" true 2>&1 | grep -E -q "<not supported>"
170 then
171 echo "Topdown weak groups test [Failed events not supported]"
172 err=1
173 return
174 fi
175 echo "Topdown weak groups test [Success]"
176}
177
178test_cputype() {
179 # Test --cputype argument.
180 echo "cputype test"
181
182 # Bogus PMU should fail.
183 if perf stat --cputype="123" -e instructions true > /dev/null 2>&1
184 then
185 echo "cputype test [Bogus PMU didn't fail]"
186 err=1
187 return
188 fi
189
190 # Find a known PMU for cputype.
191 pmu=""
192 devs="/sys/bus/event_source/devices"
193 for i in $devs/cpu $devs/cpu_atom $devs/armv8_pmuv3_0 $devs/armv8_cortex_*
194 do
195 i_base=$(basename "$i")
196 if test -d "$i"
197 then
198 pmu="$i_base"
199 break
200 fi
201 if perf stat -e "$i_base/instructions/" true > /dev/null 2>&1
202 then
203 pmu="$i_base"
204 break
205 fi
206 done
207 if test "x$pmu" = "x"
208 then
209 echo "cputype test [Skipped known PMU not found]"
210 return
211 fi
212
213 # Test running with cputype produces output.
214 if ! perf stat --cputype="$pmu" -e instructions true 2>&1 | grep -E -q "instructions"
215 then
216 echo "cputype test [Failed count missed with given filter]"
217 err=1
218 return
219 fi
220 echo "cputype test [Success]"
221}
222
223test_hybrid() {
224 # Test the default stat command on hybrid devices opens one cycles event for
225 # each CPU type.
226 echo "hybrid test"
227
228 # Count the number of core PMUs, assume minimum of 1
229 pmus=$(ls /sys/bus/event_source/devices/*/cpus 2>/dev/null | wc -l)
230 if [ "$pmus" -lt 1 ]
231 then
232 pmus=1
233 fi
234
235 # Run default Perf stat
236 cycles_events=$(perf stat -a -- sleep 0.1 2>&1 | grep -E "/cpu-cycles/[uH]*| cpu-cycles[:uH]* " -c)
237
238 # The expectation is that default output will have a cycles events on each
239 # hybrid PMU. In situations with no cycles PMU events, like virtualized, this
240 # can fall back to task-clock and so the end count may be 0. Fail if neither
241 # condition holds.
242 if [ "$pmus" -ne "$cycles_events" ] && [ "0" -ne "$cycles_events" ]
243 then
244 echo "hybrid test [Found $pmus PMUs but $cycles_events cycles events. Failed]"
245 err=1
246 return
247 fi
248 echo "hybrid test [Success]"
249}
250
251test_default_stat
252test_null_stat
253test_offline_cpu_stat
254test_stat_record_report
255test_stat_record_script
256test_stat_repeat_weak_groups
257test_topdown_groups
258test_topdown_weak_groups
259test_cputype
260test_hybrid
261exit $err