Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) Using TopDown metrics in user space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) -----------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) Intel CPUs (since Sandy Bridge and Silvermont) support a TopDown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) methology to break down CPU pipeline execution into 4 bottlenecks:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) frontend bound, backend bound, bad speculation, retiring.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) For more details on Topdown see [1][5]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) Traditionally this was implemented by events in generic counters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) and specific formulas to compute the bottlenecks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) perf stat --topdown implements this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) Full Top Down includes more levels that can break down the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) bottlenecks further. This is not directly implemented in perf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) but available in other tools that can run on top of perf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) such as toplev[2] or vtune[3]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) New Topdown features in Ice Lake
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) ===============================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) With Ice Lake CPUs the TopDown metrics are directly available as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) fixed counters and do not require generic counters. This allows
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) to collect TopDown always in addition to other events.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) % perf stat -a --topdown -I1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #           time             retiring      bad speculation       frontend bound        backend bound
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)      1.001281330                23.0%                15.3%                29.6%                32.1%
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)      2.003009005                 5.0%                 6.8%                46.6%                41.6%
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)      3.004646182                 6.7%                 6.7%                46.0%                40.6%
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)      4.006326375                 5.0%                 6.4%                47.6%                41.0%
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)      5.007991804                 5.1%                 6.3%                46.3%                42.3%
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)      6.009626773                 6.2%                 7.1%                47.3%                39.3%
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35)      7.011296356                 4.7%                 6.7%                46.2%                42.4%
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36)      8.012951831                 4.7%                 6.7%                47.5%                41.1%
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) This also enables measuring TopDown per thread/process instead
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) of only per core.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) Using TopDown through RDPMC in applications on Ice Lake
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) ======================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) For more fine grained measurements it can be useful to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) access the new  directly from user space. This is more complicated,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) but drastically lowers overhead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) On Ice Lake, there is a new fixed counter 3: SLOTS, which reports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) "pipeline SLOTS" (cycles multiplied by core issue width) and a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) metric register that reports slots ratios for the different bottleneck
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) categories.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) The metrics counter is CPU model specific and is not available on older
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) CPUs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) Example code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) ============
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) Library functions to do the functionality described below
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) is also available in libjevents [4]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) The application opens a group with fixed counter 3 (SLOTS) and any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) metric event, and allow user programs to read the performance counters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) Fixed counter 3 is mapped to a pseudo event event=0x00, umask=04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) so the perf_event_attr structure should be initialized with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) { .config = 0x0400, .type = PERF_TYPE_RAW }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) The metric events are mapped to the pseudo event event=0x00, umask=0x8X.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) For example, the perf_event_attr structure can be initialized with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) { .config = 0x8000, .type = PERF_TYPE_RAW } for Retiring metric event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) The Fixed counter 3 must be the leader of the group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) #include <linux/perf_event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) #include <sys/syscall.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) /* Provide own perf_event_open stub because glibc doesn't */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) __attribute__((weak))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) int perf_event_open(struct perf_event_attr *attr, pid_t pid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		    int cpu, int group_fd, unsigned long flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) /* Open slots counter file descriptor for current task. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) struct perf_event_attr slots = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	.type = PERF_TYPE_RAW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	.size = sizeof(struct perf_event_attr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	.config = 0x400,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	.exclude_kernel = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) int slots_fd = perf_event_open(&slots, 0, -1, -1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) if (slots_fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	... error ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99)  * Open metrics event file descriptor for current task.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)  * Set slots event as the leader of the group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct perf_event_attr metrics = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	.type = PERF_TYPE_RAW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	.size = sizeof(struct perf_event_attr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	.config = 0x8000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	.exclude_kernel = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int metrics_fd = perf_event_open(&metrics, 0, -1, slots_fd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (metrics_fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	... error ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) The RDPMC instruction (or _rdpmc compiler intrinsic) can now be used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) to read slots and the topdown metrics at different points of the program:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #include <stdint.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #include <x86intrin.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define RDPMC_FIXED	(1 << 30)	/* return fixed counters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define RDPMC_METRIC	(1 << 29)	/* return metric counters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define FIXED_COUNTER_SLOTS		3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define METRIC_COUNTER_TOPDOWN_L1	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static inline uint64_t read_slots(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	return _rdpmc(RDPMC_FIXED | FIXED_COUNTER_SLOTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static inline uint64_t read_metrics(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	return _rdpmc(RDPMC_METRIC | METRIC_COUNTER_TOPDOWN_L1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) Then the program can be instrumented to read these metrics at different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) points.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) It's not a good idea to do this with too short code regions,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) as the parallelism and overlap in the CPU program execution will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) cause too much measurement inaccuracy. For example instrumenting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) individual basic blocks is definitely too fine grained.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) Decoding metrics values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) =======================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) The value reported by read_metrics() contains four 8 bit fields
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) that represent a scaled ratio that represent the Level 1 bottleneck.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) All four fields add up to 0xff (= 100%)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) The binary ratios in the metric value can be converted to float ratios:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #define GET_METRIC(m, i) (((m) >> (i*8)) & 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #define TOPDOWN_RETIRING(val)	((float)GET_METRIC(val, 0) / 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #define TOPDOWN_BAD_SPEC(val)	((float)GET_METRIC(val, 1) / 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #define TOPDOWN_FE_BOUND(val)	((float)GET_METRIC(val, 2) / 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) #define TOPDOWN_BE_BOUND(val)	((float)GET_METRIC(val, 3) / 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) and then converted to percent for printing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) The ratios in the metric accumulate for the time when the counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) is enabled. For measuring programs it is often useful to measure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) specific sections. For this it is needed to deltas on metrics.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) This can be done by scaling the metrics with the slots counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) read at the same time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) Then it's possible to take deltas of these slots counts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) measured at different points, and determine the metrics
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) for that time period.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	slots_a = read_slots();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	metric_a = read_metrics();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	... larger code region ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	slots_b = read_slots()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	metric_b = read_metrics()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	# compute scaled metrics for measurement a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	retiring_slots_a = GET_METRIC(metric_a, 0) * slots_a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	bad_spec_slots_a = GET_METRIC(metric_a, 1) * slots_a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	fe_bound_slots_a = GET_METRIC(metric_a, 2) * slots_a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	be_bound_slots_a = GET_METRIC(metric_a, 3) * slots_a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	# compute delta scaled metrics between b and a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	retiring_slots = GET_METRIC(metric_b, 0) * slots_b - retiring_slots_a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	bad_spec_slots = GET_METRIC(metric_b, 1) * slots_b - bad_spec_slots_a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	fe_bound_slots = GET_METRIC(metric_b, 2) * slots_b - fe_bound_slots_a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	be_bound_slots = GET_METRIC(metric_b, 3) * slots_b - be_bound_slots_a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) Later the individual ratios for the measurement period can be recreated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) from these counts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	slots_delta = slots_b - slots_a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	retiring_ratio = (float)retiring_slots / slots_delta
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	bad_spec_ratio = (float)bad_spec_slots / slots_delta
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	fe_bound_ratio = (float)fe_bound_slots / slots_delta
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	be_bound_ratio = (float)be_bound_slots / slota_delta
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	printf("Retiring %.2f%% Bad Speculation %.2f%% FE Bound %.2f%% BE Bound %.2f%%\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		retiring_ratio * 100.,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		bad_spec_ratio * 100.,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		fe_bound_ratio * 100.,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		be_bound_ratio * 100.);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) Resetting metrics counters
^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) Since the individual metrics are only 8bit they lose precision for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) short regions over time because the number of cycles covered by each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) fraction bit shrinks. So the counters need to be reset regularly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) When using the kernel perf API the kernel resets on every read.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) So as long as the reading is at reasonable intervals (every few
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) seconds) the precision is good.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) When using perf stat it is recommended to always use the -I option,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) with no longer interval than a few seconds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	perf stat -I 1000 --topdown ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) For user programs using RDPMC directly the counter can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) be reset explicitly using ioctl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	ioctl(perf_fd, PERF_EVENT_IOC_RESET, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) This "opens" a new measurement period.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) A program using RDPMC for TopDown should schedule such a reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) regularly, as in every few seconds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) Limits on Ice Lake
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) ==================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) Four pseudo TopDown metric events are exposed for the end-users,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) topdown-retiring, topdown-bad-spec, topdown-fe-bound and topdown-be-bound.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) They can be used to collect the TopDown value under the following
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) rules:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) - All the TopDown metric events must be in a group with the SLOTS event.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) - The SLOTS event must be the leader of the group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) - The PERF_FORMAT_GROUP flag must be applied for each TopDown metric
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)   events
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) The SLOTS event and the TopDown metric events can be counting members of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) a sampling read group. Since the SLOTS event must be the leader of a TopDown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) group, the second event of the group is the sampling event.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) For example, perf record -e '{slots, $sampling_event, topdown-retiring}:S'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) [1] https://software.intel.com/en-us/top-down-microarchitecture-analysis-method-win
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) [2] https://github.com/andikleen/pmu-tools/wiki/toplev-manual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) [3] https://software.intel.com/en-us/intel-vtune-amplifier-xe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) [4] https://github.com/andikleen/pmu-tools/tree/master/jevents
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) [5] https://sites.google.com/site/analysismethods/yasin-pubs