xref: /aosp_15_r20/external/bcc/examples/cpp/LLCStat.cc (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker /*
2*387f9dfdSAndroid Build Coastguard Worker  * LLCStat Show LLC hit ratio for each process on each CPU core.
3*387f9dfdSAndroid Build Coastguard Worker  *         For Linux, uses BCC, eBPF. Embedded C.
4*387f9dfdSAndroid Build Coastguard Worker  *
5*387f9dfdSAndroid Build Coastguard Worker  * Basic example of BCC timed sampling perf event.
6*387f9dfdSAndroid Build Coastguard Worker  *
7*387f9dfdSAndroid Build Coastguard Worker  * USAGE: LLCStat [duration]
8*387f9dfdSAndroid Build Coastguard Worker  *
9*387f9dfdSAndroid Build Coastguard Worker  * Copyright (c) Facebook, Inc.
10*387f9dfdSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License")
11*387f9dfdSAndroid Build Coastguard Worker  */
12*387f9dfdSAndroid Build Coastguard Worker 
13*387f9dfdSAndroid Build Coastguard Worker #include <linux/perf_event.h>
14*387f9dfdSAndroid Build Coastguard Worker #include <unistd.h>
15*387f9dfdSAndroid Build Coastguard Worker #include <iomanip>
16*387f9dfdSAndroid Build Coastguard Worker #include <iostream>
17*387f9dfdSAndroid Build Coastguard Worker #include <string>
18*387f9dfdSAndroid Build Coastguard Worker 
19*387f9dfdSAndroid Build Coastguard Worker #include "BPF.h"
20*387f9dfdSAndroid Build Coastguard Worker 
21*387f9dfdSAndroid Build Coastguard Worker const std::string BPF_PROGRAM = R"(
22*387f9dfdSAndroid Build Coastguard Worker #include <linux/ptrace.h>
23*387f9dfdSAndroid Build Coastguard Worker #include <uapi/linux/bpf_perf_event.h>
24*387f9dfdSAndroid Build Coastguard Worker 
25*387f9dfdSAndroid Build Coastguard Worker struct event_t {
26*387f9dfdSAndroid Build Coastguard Worker     int cpu;
27*387f9dfdSAndroid Build Coastguard Worker     int pid;
28*387f9dfdSAndroid Build Coastguard Worker     char name[16];
29*387f9dfdSAndroid Build Coastguard Worker };
30*387f9dfdSAndroid Build Coastguard Worker 
31*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(ref_count, struct event_t);
32*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(miss_count, struct event_t);
33*387f9dfdSAndroid Build Coastguard Worker 
34*387f9dfdSAndroid Build Coastguard Worker static inline __attribute__((always_inline)) void get_key(struct event_t* key) {
35*387f9dfdSAndroid Build Coastguard Worker     key->cpu = bpf_get_smp_processor_id();
36*387f9dfdSAndroid Build Coastguard Worker     key->pid = bpf_get_current_pid_tgid();
37*387f9dfdSAndroid Build Coastguard Worker     bpf_get_current_comm(&(key->name), sizeof(key->name));
38*387f9dfdSAndroid Build Coastguard Worker }
39*387f9dfdSAndroid Build Coastguard Worker 
40*387f9dfdSAndroid Build Coastguard Worker int on_cache_miss(struct bpf_perf_event_data *ctx) {
41*387f9dfdSAndroid Build Coastguard Worker     struct event_t key = {};
42*387f9dfdSAndroid Build Coastguard Worker     get_key(&key);
43*387f9dfdSAndroid Build Coastguard Worker 
44*387f9dfdSAndroid Build Coastguard Worker     u64 zero = 0, *val;
45*387f9dfdSAndroid Build Coastguard Worker     val = miss_count.lookup_or_try_init(&key, &zero);
46*387f9dfdSAndroid Build Coastguard Worker     if (val) {
47*387f9dfdSAndroid Build Coastguard Worker         (*val) += ctx->sample_period;
48*387f9dfdSAndroid Build Coastguard Worker     }
49*387f9dfdSAndroid Build Coastguard Worker 
50*387f9dfdSAndroid Build Coastguard Worker     return 0;
51*387f9dfdSAndroid Build Coastguard Worker }
52*387f9dfdSAndroid Build Coastguard Worker 
53*387f9dfdSAndroid Build Coastguard Worker int on_cache_ref(struct bpf_perf_event_data *ctx) {
54*387f9dfdSAndroid Build Coastguard Worker     struct event_t key = {};
55*387f9dfdSAndroid Build Coastguard Worker     get_key(&key);
56*387f9dfdSAndroid Build Coastguard Worker 
57*387f9dfdSAndroid Build Coastguard Worker     u64 zero = 0, *val;
58*387f9dfdSAndroid Build Coastguard Worker     val = ref_count.lookup_or_try_init(&key, &zero);
59*387f9dfdSAndroid Build Coastguard Worker     if (val) {
60*387f9dfdSAndroid Build Coastguard Worker         (*val) += ctx->sample_period;
61*387f9dfdSAndroid Build Coastguard Worker     }
62*387f9dfdSAndroid Build Coastguard Worker 
63*387f9dfdSAndroid Build Coastguard Worker     return 0;
64*387f9dfdSAndroid Build Coastguard Worker }
65*387f9dfdSAndroid Build Coastguard Worker )";
66*387f9dfdSAndroid Build Coastguard Worker 
67*387f9dfdSAndroid Build Coastguard Worker struct event_t {
68*387f9dfdSAndroid Build Coastguard Worker   int cpu;
69*387f9dfdSAndroid Build Coastguard Worker   int pid;
70*387f9dfdSAndroid Build Coastguard Worker   char name[16];
71*387f9dfdSAndroid Build Coastguard Worker };
72*387f9dfdSAndroid Build Coastguard Worker 
main(int argc,char ** argv)73*387f9dfdSAndroid Build Coastguard Worker int main(int argc, char** argv) {
74*387f9dfdSAndroid Build Coastguard Worker   ebpf::BPF bpf;
75*387f9dfdSAndroid Build Coastguard Worker   auto init_res = bpf.init(BPF_PROGRAM);
76*387f9dfdSAndroid Build Coastguard Worker   if (!init_res.ok()) {
77*387f9dfdSAndroid Build Coastguard Worker     std::cerr << init_res.msg() << std::endl;
78*387f9dfdSAndroid Build Coastguard Worker     return 1;
79*387f9dfdSAndroid Build Coastguard Worker   }
80*387f9dfdSAndroid Build Coastguard Worker 
81*387f9dfdSAndroid Build Coastguard Worker   auto attach_ref_res =
82*387f9dfdSAndroid Build Coastguard Worker       bpf.attach_perf_event(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES,
83*387f9dfdSAndroid Build Coastguard Worker                             "on_cache_ref", 100, 0);
84*387f9dfdSAndroid Build Coastguard Worker   if (!attach_ref_res.ok()) {
85*387f9dfdSAndroid Build Coastguard Worker     std::cerr << attach_ref_res.msg() << std::endl;
86*387f9dfdSAndroid Build Coastguard Worker     return 1;
87*387f9dfdSAndroid Build Coastguard Worker   }
88*387f9dfdSAndroid Build Coastguard Worker   auto attach_miss_res = bpf.attach_perf_event(
89*387f9dfdSAndroid Build Coastguard Worker       PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES, "on_cache_miss", 100, 0);
90*387f9dfdSAndroid Build Coastguard Worker   if (!attach_miss_res.ok()) {
91*387f9dfdSAndroid Build Coastguard Worker     std::cerr << attach_miss_res.msg() << std::endl;
92*387f9dfdSAndroid Build Coastguard Worker     return 1;
93*387f9dfdSAndroid Build Coastguard Worker   }
94*387f9dfdSAndroid Build Coastguard Worker 
95*387f9dfdSAndroid Build Coastguard Worker   int probe_time = 10;
96*387f9dfdSAndroid Build Coastguard Worker   if (argc == 2) {
97*387f9dfdSAndroid Build Coastguard Worker     probe_time = atoi(argv[1]);
98*387f9dfdSAndroid Build Coastguard Worker   }
99*387f9dfdSAndroid Build Coastguard Worker   std::cout << "Probing for " << probe_time << " seconds" << std::endl;
100*387f9dfdSAndroid Build Coastguard Worker   sleep(probe_time);
101*387f9dfdSAndroid Build Coastguard Worker   bpf.detach_perf_event(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES);
102*387f9dfdSAndroid Build Coastguard Worker   bpf.detach_perf_event(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES);
103*387f9dfdSAndroid Build Coastguard Worker 
104*387f9dfdSAndroid Build Coastguard Worker   auto refs = bpf.get_hash_table<event_t, uint64_t>("ref_count");
105*387f9dfdSAndroid Build Coastguard Worker   auto misses = bpf.get_hash_table<event_t, uint64_t>("miss_count");
106*387f9dfdSAndroid Build Coastguard Worker   for (auto it : refs.get_table_offline()) {
107*387f9dfdSAndroid Build Coastguard Worker     uint64_t hit;
108*387f9dfdSAndroid Build Coastguard Worker     try {
109*387f9dfdSAndroid Build Coastguard Worker       auto miss = misses[it.first];
110*387f9dfdSAndroid Build Coastguard Worker       hit = miss <= it.second ? it.second - miss : 0;
111*387f9dfdSAndroid Build Coastguard Worker     } catch (...) {
112*387f9dfdSAndroid Build Coastguard Worker       hit = it.second;
113*387f9dfdSAndroid Build Coastguard Worker     }
114*387f9dfdSAndroid Build Coastguard Worker     double ratio = (double(hit) / double(it.second)) * 100.0;
115*387f9dfdSAndroid Build Coastguard Worker     std::cout << "PID " << std::setw(8) << std::setfill(' ') << it.first.pid;
116*387f9dfdSAndroid Build Coastguard Worker     std::cout << std::setw(20) << std::setfill(' ') << std::left
117*387f9dfdSAndroid Build Coastguard Worker               << " (" + std::string(it.first.name) + ") " << std::right;
118*387f9dfdSAndroid Build Coastguard Worker     std::cout << "on CPU " << std::setw(2) << std::setfill(' ') << it.first.cpu;
119*387f9dfdSAndroid Build Coastguard Worker     std::cout << " Hit Rate " << std::setprecision(4) << ratio << "% ";
120*387f9dfdSAndroid Build Coastguard Worker     std::cout << "(" << hit << "/" << it.second << ")" << std::endl;
121*387f9dfdSAndroid Build Coastguard Worker   }
122*387f9dfdSAndroid Build Coastguard Worker   return 0;
123*387f9dfdSAndroid Build Coastguard Worker }
124