blob: 0dfc232d8a2f0cc8457b88c5866a4af32a1c98d1 [file] [log] [blame]
Teng Qine960eb72016-10-18 17:22:27 -07001#!/usr/bin/python
2#
3# llcstat.py Summarize cache references and cache misses by PID.
4# Cache reference and cache miss are corresponding events defined in
5# uapi/linux/perf_event.h, it varies to different architecture.
6# On x86-64, they mean LLC references and LLC misses.
7#
8# For Linux, uses BCC, eBPF. Embedded C.
9#
10# REQUIRES: Linux 4.9+ (BPF_PROG_TYPE_PERF_EVENT support).
11#
12# Copyright (c) 2016 Facebook, Inc.
13# Licensed under the Apache License, Version 2.0 (the "License")
14#
15# 19-Oct-2016 Teng Qin Created this.
16
17from __future__ import print_function
18import argparse
19from bcc import BPF, PerfType, PerfHWConfig
20import signal
21from time import sleep
22
23parser = argparse.ArgumentParser(
24 description="Summarize cache references and misses by PID",
25 formatter_class=argparse.RawDescriptionHelpFormatter)
26parser.add_argument(
27 "-c", "--sample_period", type=int, default=100,
28 help="Sample one in this many number of cache reference / miss events")
29parser.add_argument(
30 "duration", nargs="?", default=10, help="Duration, in seconds, to run")
Nathan Scottcf0792f2018-02-02 16:56:50 +110031parser.add_argument("--ebpf", action="store_true",
32 help=argparse.SUPPRESS)
Teng Qine960eb72016-10-18 17:22:27 -070033args = parser.parse_args()
34
35# load BPF program
Nathan Scottcf0792f2018-02-02 16:56:50 +110036bpf_text="""
Teng Qine960eb72016-10-18 17:22:27 -070037#include <linux/ptrace.h>
38#include <uapi/linux/bpf_perf_event.h>
39
40struct key_t {
41 int cpu;
42 int pid;
43 char name[TASK_COMM_LEN];
44};
45
46BPF_HASH(ref_count, struct key_t);
47BPF_HASH(miss_count, struct key_t);
48
49static inline __attribute__((always_inline)) void get_key(struct key_t* key) {
50 key->cpu = bpf_get_smp_processor_id();
51 key->pid = bpf_get_current_pid_tgid();
52 bpf_get_current_comm(&(key->name), sizeof(key->name));
53}
54
55int on_cache_miss(struct bpf_perf_event_data *ctx) {
56 struct key_t key = {};
57 get_key(&key);
58
59 u64 zero = 0, *val;
60 val = miss_count.lookup_or_init(&key, &zero);
61 (*val) += ctx->sample_period;
62
63 return 0;
64}
65
66int on_cache_ref(struct bpf_perf_event_data *ctx) {
67 struct key_t key = {};
68 get_key(&key);
69
70 u64 zero = 0, *val;
71 val = ref_count.lookup_or_init(&key, &zero);
72 (*val) += ctx->sample_period;
73
74 return 0;
75}
Nathan Scottcf0792f2018-02-02 16:56:50 +110076"""
Teng Qine960eb72016-10-18 17:22:27 -070077
Nathan Scottcf0792f2018-02-02 16:56:50 +110078if args.ebpf:
79 print(bpf_text)
80 exit()
81
82b = BPF(text=bpf_text)
Teng Qine960eb72016-10-18 17:22:27 -070083b.attach_perf_event(
84 ev_type=PerfType.HARDWARE, ev_config=PerfHWConfig.CACHE_MISSES,
85 fn_name="on_cache_miss", sample_period=args.sample_period)
86b.attach_perf_event(
87 ev_type=PerfType.HARDWARE, ev_config=PerfHWConfig.CACHE_REFERENCES,
88 fn_name="on_cache_ref", sample_period=args.sample_period)
89
90print("Running for {} seconds or hit Ctrl-C to end.".format(args.duration))
91
92try:
93 sleep(float(args.duration))
94except KeyboardInterrupt:
95 signal.signal(signal.SIGINT, lambda signal, frame: print())
96
97miss_count = {}
98for (k, v) in b.get_table('miss_count').items():
99 miss_count[(k.pid, k.cpu, k.name)] = v.value
100
101print('PID NAME CPU REFERENCE MISS HIT%')
102tot_ref = 0
103tot_miss = 0
104for (k, v) in b.get_table('ref_count').items():
105 try:
106 miss = miss_count[(k.pid, k.cpu, k.name)]
107 except KeyError:
108 miss = 0
109 tot_ref += v.value
110 tot_miss += miss
111 # This happens on some PIDs due to missed counts caused by sampling
112 hit = (v.value - miss) if (v.value >= miss) else 0
113 print('{:<8d} {:<16s} {:<4d} {:>12d} {:>12d} {:>6.2f}%'.format(
Rafael Fonsecaf2e6b8d2017-02-15 15:20:52 +0100114 k.pid, k.name.decode(), k.cpu, v.value, miss,
Teng Qine960eb72016-10-18 17:22:27 -0700115 (float(hit) / float(v.value)) * 100.0))
116print('Total References: {} Total Misses: {} Hit Rate: {:.2f}%'.format(
117 tot_ref, tot_miss, (float(tot_ref - tot_miss) / float(tot_ref)) * 100.0))