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