xref: /linux/tools/perf/pmu-events/amd_metrics.py (revision b2128290c29902315e632ea59e0504d6bc9e9b42)
1#!/usr/bin/env python3
2# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
3import argparse
4import math
5import os
6from typing import Optional
7from common_metrics import Cycles
8from metric import (d_ratio, has_event, max, Event, JsonEncodeMetric,
9                    JsonEncodeMetricGroupDescriptions, Literal, LoadEvents,
10                    Metric, MetricGroup, Select)
11
12# Global command line arguments.
13_args = None
14_zen_model: int = 1
15interval_sec = Event("duration_time")
16ins = Event("instructions")
17cycles = Event("cycles")
18# Number of CPU cycles scaled for SMT.
19smt_cycles = Select(cycles / 2, Literal("#smt_on"), cycles)
20
21
22def AmdBr():
23    def Total() -> MetricGroup:
24        br = Event("ex_ret_brn")
25        br_m_all = Event("ex_ret_brn_misp")
26        br_clr = Event("ex_ret_brn_cond_misp",
27                       "ex_ret_msprd_brnch_instr_dir_msmtch",
28                       "ex_ret_brn_resync")
29
30        br_r = d_ratio(br, interval_sec)
31        ins_r = d_ratio(ins, br)
32        misp_r = d_ratio(br_m_all, br)
33        clr_r = d_ratio(br_clr, interval_sec)
34
35        return MetricGroup("lpm_br_total", [
36            Metric("lpm_br_total_retired",
37                   "The number of branch instructions retired per second.", br_r,
38                   "insn/s"),
39            Metric(
40                "lpm_br_total_mispred",
41                "The number of branch instructions retired, of any type, that were "
42                "not correctly predicted as a percentage of all branch instrucions.",
43                misp_r, "100%"),
44            Metric("lpm_br_total_insn_between_branches",
45                   "The number of instructions divided by the number of branches.",
46                   ins_r, "insn"),
47            Metric("lpm_br_total_insn_fe_resteers",
48                   "The number of resync branches per second.", clr_r, "req/s")
49        ])
50
51    def Taken() -> MetricGroup:
52        br = Event("ex_ret_brn_tkn")
53        br_m_tk = Event("ex_ret_brn_tkn_misp")
54        br_r = d_ratio(br, interval_sec)
55        ins_r = d_ratio(ins, br)
56        misp_r = d_ratio(br_m_tk, br)
57        return MetricGroup("lpm_br_taken", [
58            Metric("lpm_br_taken_retired",
59                   "The number of taken branches that were retired per second.",
60                   br_r, "insn/s"),
61            Metric(
62                "lpm_br_taken_mispred",
63                "The number of retired taken branch instructions that were "
64                "mispredicted as a percentage of all taken branches.", misp_r,
65                "100%"),
66            Metric(
67                "lpm_br_taken_insn_between_branches",
68                "The number of instructions divided by the number of taken branches.",
69                ins_r, "insn"),
70        ])
71
72    def Conditional() -> Optional[MetricGroup]:
73        global _zen_model
74        br = Event("ex_ret_brn_cond", "ex_ret_cond")
75        br_r = d_ratio(br, interval_sec)
76        ins_r = d_ratio(ins, br)
77
78        metrics = [
79            Metric("lpm_br_cond_retired", "Retired conditional branch instructions.",
80                   br_r, "insn/s"),
81            Metric("lpm_br_cond_insn_between_branches",
82                   "The number of instructions divided by the number of conditional "
83                   "branches.", ins_r, "insn"),
84        ]
85        if _zen_model == 2:
86            br_m_cond = Event("ex_ret_cond_misp")
87            misp_r = d_ratio(br_m_cond, br)
88            metrics += [
89                Metric("lpm_br_cond_mispred",
90                       "Retired conditional branch instructions mispredicted as a "
91                       "percentage of all conditional branches.", misp_r, "100%"),
92            ]
93
94        return MetricGroup("lpm_br_cond", metrics)
95
96    def Fused() -> MetricGroup:
97        br = Event("ex_ret_fused_instr", "ex_ret_fus_brnch_inst")
98        br_r = d_ratio(br, interval_sec)
99        ins_r = d_ratio(ins, br)
100        return MetricGroup("lpm_br_cond", [
101            Metric("lpm_br_fused_retired",
102                   "Retired fused branch instructions per second.", br_r, "insn/s"),
103            Metric(
104                "lpm_br_fused_insn_between_branches",
105                "The number of instructions divided by the number of fused "
106                "branches.", ins_r, "insn"),
107        ])
108
109    def Far() -> MetricGroup:
110        br = Event("ex_ret_brn_far")
111        br_r = d_ratio(br, interval_sec)
112        ins_r = d_ratio(ins, br)
113        return MetricGroup("lpm_br_far", [
114            Metric("lpm_br_far_retired", "Retired far control transfers per second.",
115                   br_r, "insn/s"),
116            Metric(
117                "lpm_br_far_insn_between_branches",
118                "The number of instructions divided by the number of far branches.",
119                ins_r, "insn"),
120        ])
121
122    return MetricGroup("lpm_br", [Total(), Taken(), Conditional(), Fused(), Far()],
123                       description="breakdown of retired branch instructions")
124
125
126def AmdCtxSw() -> MetricGroup:
127    cs = Event("context\\-switches")
128    metrics = [
129        Metric("lpm_cs_rate", "Context switches per second",
130               d_ratio(cs, interval_sec), "ctxsw/s")
131    ]
132
133    ev = Event("instructions")
134    metrics.append(Metric("lpm_cs_instr", "Instructions per context switch",
135                          d_ratio(ev, cs), "instr/cs"))
136
137    ev = Event("cycles")
138    metrics.append(Metric("lpm_cs_cycles", "Cycles per context switch",
139                          d_ratio(ev, cs), "cycles/cs"))
140
141    ev = Event("ls_dispatch.pure_ld", "ls_dispatch.ld_dispatch")
142    metrics.append(Metric("lpm_cs_loads", "Loads per context switch",
143                          d_ratio(ev, cs), "loads/cs"))
144
145    ev = Event("ls_dispatch.pure_st", "ls_dispatch.store_dispatch")
146    metrics.append(Metric("lpm_cs_stores", "Stores per context switch",
147                          d_ratio(ev, cs), "stores/cs"))
148
149    ev = Event("ex_ret_brn_tkn")
150    metrics.append(Metric("lpm_cs_br_taken", "Branches taken per context switch",
151                          d_ratio(ev, cs), "br_taken/cs"))
152
153    return MetricGroup("lpm_cs", metrics,
154                       description=("Number of context switches per second, instructions "
155                                    "retired & core cycles between context switches"))
156
157
158def AmdDtlb() -> Optional[MetricGroup]:
159    global _zen_model
160    if _zen_model >= 4:
161        return None
162
163    d_dat = Event("ls_dc_accesses") if _zen_model <= 3 else None
164    d_h4k = Event("ls_l1_d_tlb_miss.tlb_reload_4k_l2_hit")
165    d_hcoal = Event(
166        "ls_l1_d_tlb_miss.tlb_reload_coalesced_page_hit") if _zen_model >= 2 else 0
167    d_h2m = Event("ls_l1_d_tlb_miss.tlb_reload_2m_l2_hit")
168    d_h1g = Event("ls_l1_d_tlb_miss.tlb_reload_1g_l2_hit")
169
170    d_m4k = Event("ls_l1_d_tlb_miss.tlb_reload_4k_l2_miss")
171    d_mcoal = Event(
172        "ls_l1_d_tlb_miss.tlb_reload_coalesced_page_miss") if _zen_model >= 2 else 0
173    d_m2m = Event("ls_l1_d_tlb_miss.tlb_reload_2m_l2_miss")
174    d_m1g = Event("ls_l1_d_tlb_miss.tlb_reload_1g_l2_miss")
175
176    d_w0 = Event("ls_tablewalker.dc_type0") if _zen_model <= 3 else None
177    d_w1 = Event("ls_tablewalker.dc_type1") if _zen_model <= 3 else None
178    walks = d_w0 + d_w1
179    walks_r = d_ratio(walks, interval_sec)
180    ins_w = d_ratio(ins, walks)
181    l1 = d_dat
182    l1_r = d_ratio(l1, interval_sec)
183    l2_hits = d_h4k + d_hcoal + d_h2m + d_h1g
184    l2_miss = d_m4k + d_mcoal + d_m2m + d_m1g
185    l2_r = d_ratio(l2_hits + l2_miss, interval_sec)
186    l1_miss = l2_hits + l2_miss + walks
187    l1_hits = max(l1 - l1_miss, 0)
188    ins_l = d_ratio(ins, l1_miss)
189
190    return MetricGroup("lpm_dtlb", [
191        MetricGroup("lpm_dtlb_ov", [
192            Metric("lpm_dtlb_ov_insn_bt_l1_miss",
193                   "DTLB overview: instructions between l1 misses.", ins_l,
194                   "insns"),
195            Metric("lpm_dtlb_ov_insn_bt_walks",
196                   "DTLB overview: instructions between dtlb page table walks.",
197                   ins_w, "insns"),
198        ]),
199        MetricGroup("lpm_dtlb_l1", [
200            Metric("lpm_dtlb_l1_hits",
201                   "DTLB L1 hits as percentage of all DTLB L1 accesses.",
202                   d_ratio(l1_hits, l1), "100%"),
203            Metric("lpm_dtlb_l1_miss",
204                   "DTLB L1 misses as percentage of all DTLB L1 accesses.",
205                   d_ratio(l1_miss, l1), "100%"),
206            Metric("lpm_dtlb_l1_reqs", "DTLB L1 accesses per second.", l1_r,
207                   "insns/s"),
208        ]),
209        MetricGroup("lpm_dtlb_l2", [
210            Metric("lpm_dtlb_l2_hits",
211                   "DTLB L2 hits as percentage of all DTLB L2 accesses.",
212                   d_ratio(l2_hits, l2_hits + l2_miss), "100%"),
213            Metric("lpm_dtlb_l2_miss",
214                   "DTLB L2 misses as percentage of all DTLB L2 accesses.",
215                   d_ratio(l2_miss, l2_hits + l2_miss), "100%"),
216            Metric("lpm_dtlb_l2_reqs", "DTLB L2 accesses per second.", l2_r,
217                   "insns/s"),
218            MetricGroup("lpm_dtlb_l2_4kb", [
219                Metric(
220                    "lpm_dtlb_l2_4kb_hits",
221                    "DTLB L2 4kb page size hits as percentage of all DTLB L2 4kb "
222                    "accesses.", d_ratio(d_h4k, d_h4k + d_m4k), "100%"),
223                Metric(
224                    "lpm_dtlb_l2_4kb_miss",
225                    "DTLB L2 4kb page size misses as percentage of all DTLB L2 4kb"
226                    "accesses.", d_ratio(d_m4k, d_h4k + d_m4k), "100%")
227            ]),
228            MetricGroup("lpm_dtlb_l2_coalesced", [
229                Metric(
230                    "lpm_dtlb_l2_coal_hits",
231                    "DTLB L2 coalesced page (16kb) hits as percentage of all DTLB "
232                    "L2 coalesced accesses.", d_ratio(d_hcoal,
233                                                      d_hcoal + d_mcoal), "100%"),
234                Metric(
235                    "lpm_dtlb_l2_coal_miss",
236                    "DTLB L2 coalesced page (16kb) misses as percentage of all "
237                    "DTLB L2 coalesced accesses.",
238                    d_ratio(d_mcoal, d_hcoal + d_mcoal), "100%")
239            ]),
240            MetricGroup("lpm_dtlb_l2_2mb", [
241                Metric(
242                    "lpm_dtlb_l2_2mb_hits",
243                    "DTLB L2 2mb page size hits as percentage of all DTLB L2 2mb "
244                    "accesses.", d_ratio(d_h2m, d_h2m + d_m2m), "100%"),
245                Metric(
246                    "lpm_dtlb_l2_2mb_miss",
247                    "DTLB L2 2mb page size misses as percentage of all DTLB L2 "
248                    "accesses.", d_ratio(d_m2m, d_h2m + d_m2m), "100%")
249            ]),
250            MetricGroup("lpm_dtlb_l2_1g", [
251                Metric(
252                    "lpm_dtlb_l2_1g_hits",
253                    "DTLB L2 1gb page size hits as percentage of all DTLB L2 1gb "
254                    "accesses.", d_ratio(d_h1g, d_h1g + d_m1g), "100%"),
255                Metric(
256                    "lpm_dtlb_l2_1g_miss",
257                    "DTLB L2 1gb page size misses as percentage of all DTLB L2 "
258                    "1gb accesses.", d_ratio(d_m1g, d_h1g + d_m1g), "100%")
259            ]),
260        ]),
261        MetricGroup("lpm_dtlb_walks", [
262            Metric("lpm_dtlb_walks_reqs", "DTLB page table walks per second.",
263                   walks_r, "walks/s"),
264        ]),
265    ], description="Data TLB metrics")
266
267
268def AmdIotlb() -> Optional[MetricGroup]:
269    global _zen_model
270    if _zen_model < 2:
271        return None
272
273    # On AMD, the pde events cover both 2M and 1G pages.
274    total_hit = Event("amd_iommu/mem_iommu_tlb_pte_hit/") + Event(
275        "amd_iommu/mem_iommu_tlb_pde_hit/"
276    )
277    total_miss = Event("amd_iommu/mem_iommu_tlb_pte_mis/") + Event(
278        "amd_iommu/mem_iommu_tlb_pde_mis/"
279    )
280    miss_rate = d_ratio(total_miss, total_miss + total_hit)
281
282    interrupt_cache_hit = Event("amd_iommu/int_dte_hit/")
283    interrupt_cache_miss = Event("amd_iommu/int_dte_mis/")
284    interrupt_cache_lookup = interrupt_cache_hit + interrupt_cache_miss
285    interrupt_cache_miss_rate = d_ratio(
286        interrupt_cache_miss, interrupt_cache_miss + interrupt_cache_hit
287    )
288
289    return MetricGroup(
290        "iotlb",
291        [
292            Metric("iotlb_total_hit", "IOTLB total hit", total_hit, "hits"),
293            Metric("iotlb_total_miss", "IOTLB total miss", total_miss, "misses"),
294            Metric("iotlb_miss_rate", "IOTLB miss rate", miss_rate, "100%"),
295            Metric(
296                "iotlb_interrupt_cache_hit",
297                "IOTLB interrupt cache hit",
298                interrupt_cache_hit,
299                "hits",
300            ),
301            Metric(
302                "iotlb_interrupt_cache_miss",
303                "IOTLB interrupt cache miss",
304                interrupt_cache_miss,
305                "misses",
306            ),
307            Metric(
308                "iotlb_interrupt_cache_lookup",
309                "IOTLB interrupt cache lookup",
310                interrupt_cache_lookup,
311                "lookups",
312            ),
313            Metric(
314                "iotlb_interrupt_cache_miss_rate",
315                "IOTLB interrupt cache miss rate",
316                interrupt_cache_miss_rate,
317                "100%",
318            ),
319        ],
320        description="IOMMU TLB metrics",
321    )
322
323
324def AmdItlb():
325    global _zen_model
326    l2h = Event("bp_l1_tlb_miss_l2_tlb_hit", "bp_l1_tlb_miss_l2_hit")
327    l2m = Event("bp_l1_tlb_miss_l2_tlb_miss.all", "l2_itlb_misses",)
328    l2r = l2h + l2m
329
330    itlb_l1_mg = None
331    l1m = l2r
332    if _zen_model <= 3:
333        l1r = Event("ic_fw32")
334        l1h = max(l1r - l1m, 0)
335        itlb_l1_mg = MetricGroup("lpm_itlb_l1", [
336            Metric("lpm_itlb_l1_hits",
337                   "L1 ITLB hits as a perecentage of L1 ITLB accesses.",
338                   d_ratio(l1h, l1h + l1m), "100%"),
339            Metric("lpm_itlb_l1_miss",
340                   "L1 ITLB misses as a perecentage of L1 ITLB accesses.",
341                   d_ratio(l1m, l1h + l1m), "100%"),
342            Metric("lpm_itlb_l1_reqs",
343                   "The number of 32B fetch windows transferred from IC pipe to DE "
344                   "instruction decoder per second.", d_ratio(
345                       l1r, interval_sec),
346                   "windows/sec"),
347        ])
348
349    return MetricGroup("lpm_itlb", [
350        MetricGroup("lpm_itlb_ov", [
351            Metric("lpm_itlb_ov_insn_bt_l1_miss",
352                   "Number of instructions between l1 misses", d_ratio(
353                       ins, l1m), "insns"),
354            Metric("lpm_itlb_ov_insn_bt_l2_miss",
355                   "Number of instructions between l2 misses", d_ratio(
356                       ins, l2m), "insns"),
357        ]),
358        itlb_l1_mg,
359        MetricGroup("lpm_itlb_l2", [
360            Metric("lpm_itlb_l2_hits",
361                   "L2 ITLB hits as a percentage of all L2 ITLB accesses.",
362                   d_ratio(l2h, l2r), "100%"),
363            Metric("lpm_itlb_l2_miss",
364                   "L2 ITLB misses as a percentage of all L2 ITLB accesses.",
365                   d_ratio(l2m, l2r), "100%"),
366            Metric("lpm_itlb_l2_reqs", "ITLB accesses per second.",
367                   d_ratio(l2r, interval_sec), "accesses/sec"),
368        ]),
369    ], description="Instruction TLB breakdown")
370
371
372def AmdLdSt() -> MetricGroup:
373    ldst_ld = Event("ls_dispatch.pure_ld", "ls_dispatch.ld_dispatch")
374    ldst_st = Event("ls_dispatch.pure_st", "ls_dispatch.store_dispatch")
375    ldst_ldc1 = Event(f"{ldst_ld}/cmask=1/")
376    ldst_stc1 = Event(f"{ldst_st}/cmask=1/")
377    ldst_ldc2 = Event(f"{ldst_ld}/cmask=2/")
378    ldst_stc2 = Event(f"{ldst_st}/cmask=2/")
379    ldst_ldc3 = Event(f"{ldst_ld}/cmask=3/")
380    ldst_stc3 = Event(f"{ldst_st}/cmask=3/")
381    ldst_cyc = Event("ls_not_halted_cyc")
382
383    ld_rate = d_ratio(ldst_ld, interval_sec)
384    st_rate = d_ratio(ldst_st, interval_sec)
385
386    ld_v1 = max(ldst_ldc1 - ldst_ldc2, 0)
387    ld_v2 = max(ldst_ldc2 - ldst_ldc3, 0)
388    ld_v3 = ldst_ldc3
389
390    st_v1 = max(ldst_stc1 - ldst_stc2, 0)
391    st_v2 = max(ldst_stc2 - ldst_stc3, 0)
392    st_v3 = ldst_stc3
393
394    return MetricGroup("lpm_ldst", [
395        MetricGroup("lpm_ldst_total", [
396            Metric("lpm_ldst_total_ld", "Number of loads dispatched per second.",
397                   ld_rate, "insns/sec"),
398            Metric("lpm_ldst_total_st", "Number of stores dispatched per second.",
399                   st_rate, "insns/sec"),
400        ]),
401        MetricGroup("lpm_ldst_percent_insn", [
402            Metric("lpm_ldst_percent_insn_ld",
403                   "Load instructions as a percentage of all instructions.",
404                   d_ratio(ldst_ld, ins), "100%"),
405            Metric("lpm_ldst_percent_insn_st",
406                   "Store instructions as a percentage of all instructions.",
407                   d_ratio(ldst_st, ins), "100%"),
408        ]),
409        MetricGroup("lpm_ldst_ret_loads_per_cycle", [
410            Metric(
411                "lpm_ldst_ret_loads_per_cycle_1",
412                "Load instructions retiring in 1 cycle as a percentage of all "
413                "unhalted cycles.", d_ratio(ld_v1, ldst_cyc), "100%"),
414            Metric(
415                "lpm_ldst_ret_loads_per_cycle_2",
416                "Load instructions retiring in 2 cycles as a percentage of all "
417                "unhalted cycles.", d_ratio(ld_v2, ldst_cyc), "100%"),
418            Metric(
419                "lpm_ldst_ret_loads_per_cycle_3",
420                "Load instructions retiring in 3 or more cycles as a percentage"
421                "of all unhalted cycles.", d_ratio(ld_v3, ldst_cyc), "100%"),
422        ]),
423        MetricGroup("lpm_ldst_ret_stores_per_cycle", [
424            Metric(
425                "lpm_ldst_ret_stores_per_cycle_1",
426                "Store instructions retiring in 1 cycle as a percentage of all "
427                "unhalted cycles.", d_ratio(st_v1, ldst_cyc), "100%"),
428            Metric(
429                "lpm_ldst_ret_stores_per_cycle_2",
430                "Store instructions retiring in 2 cycles as a percentage of all "
431                "unhalted cycles.", d_ratio(st_v2, ldst_cyc), "100%"),
432            Metric(
433                "lpm_ldst_ret_stores_per_cycle_3",
434                "Store instructions retiring in 3 or more cycles as a percentage"
435                "of all unhalted cycles.", d_ratio(st_v3, ldst_cyc), "100%"),
436        ]),
437        MetricGroup("lpm_ldst_insn_bt", [
438            Metric("lpm_ldst_insn_bt_ld", "Number of instructions between loads.",
439                   d_ratio(ins, ldst_ld), "insns"),
440            Metric("lpm_ldst_insn_bt_st", "Number of instructions between stores.",
441                   d_ratio(ins, ldst_st), "insns"),
442        ])
443    ], description="Breakdown of load/store instructions")
444
445
446def AmdUpc() -> Metric:
447    ops = Event("ex_ret_ops", "ex_ret_cops")
448    upc = d_ratio(ops, smt_cycles)
449    return Metric("lpm_upc", "Micro-ops retired per core cycle (higher is better)",
450                  upc, "uops/cycle")
451
452
453def Idle() -> Metric:
454    cyc = Event("msr/mperf/")
455    tsc = Event("msr/tsc/")
456    low = max(tsc - cyc, 0)
457    return Metric(
458        "lpm_idle",
459        "Percentage of total wallclock cycles where CPUs are in low power state (C1 or deeper sleep state)",
460        d_ratio(low, tsc), "100%")
461
462
463def Rapl() -> MetricGroup:
464    """Processor socket power consumption estimate.
465
466    Use events from the running average power limit (RAPL) driver.
467    """
468    # Watts = joules/second
469    # Currently only energy-pkg is supported by AMD:
470    # https://lore.kernel.org/lkml/20220105185659.643355-1-eranian@google.com/
471    pkg = Event("power/energy\\-pkg/")
472    cond_pkg = Select(pkg, has_event(pkg), math.nan)
473    scale = 2.3283064365386962890625e-10
474    metrics = [
475        Metric("lpm_cpu_power_pkg", "",
476               d_ratio(cond_pkg * scale, interval_sec), "Watts"),
477    ]
478
479    return MetricGroup("lpm_cpu_power", metrics,
480                       description="Processor socket power consumption estimates")
481
482
483def UncoreL3():
484    acc = Event("l3_lookup_state.all_coherent_accesses_to_l3",
485                "l3_lookup_state.all_l3_req_typs")
486    miss = Event("l3_lookup_state.l3_miss",
487                 "l3_comb_clstr_state.request_miss")
488    acc = max(acc, miss)
489    hits = acc - miss
490
491    return MetricGroup("lpm_l3", [
492        Metric("lpm_l3_accesses", "L3 victim cache accesses",
493               d_ratio(acc, interval_sec), "accesses/sec"),
494        Metric("lpm_l3_hits", "L3 victim cache hit rate",
495               d_ratio(hits, acc), "100%"),
496        Metric("lpm_l3_miss", "L3 victim cache miss rate", d_ratio(miss, acc),
497               "100%"),
498    ], description="L3 cache breakdown per CCX")
499
500
501def main() -> None:
502    global _args
503    global _zen_model
504
505    def dir_path(path: str) -> str:
506        """Validate path is a directory for argparse."""
507        if os.path.isdir(path):
508            return path
509        raise argparse.ArgumentTypeError(
510            f'\'{path}\' is not a valid directory')
511
512    parser = argparse.ArgumentParser(description="AMD perf json generator")
513    parser.add_argument(
514        "-metricgroups", help="Generate metricgroups data", action='store_true')
515    parser.add_argument("model", help="e.g. amdzen[123]")
516    parser.add_argument(
517        'events_path',
518        type=dir_path,
519        help='Root of tree containing architecture directories containing json files'
520    )
521    _args = parser.parse_args()
522
523    directory = f"{_args.events_path}/x86/{_args.model}/"
524    LoadEvents(directory)
525
526    _zen_model = int(_args.model[6:])
527
528    all_metrics = MetricGroup("", [
529        AmdBr(),
530        AmdCtxSw(),
531        AmdDtlb(),
532        AmdIotlb(),
533        AmdItlb(),
534        AmdLdSt(),
535        AmdUpc(),
536        Cycles(),
537        Idle(),
538        Rapl(),
539        UncoreL3(),
540    ])
541
542    if _args.metricgroups:
543        print(JsonEncodeMetricGroupDescriptions(all_metrics))
544    else:
545        print(JsonEncodeMetric(all_metrics))
546
547
548if __name__ == '__main__':
549    main()
550