-
Notifications
You must be signed in to change notification settings - Fork 1
/
llc_cpuwise_histogram.py
executable file
·135 lines (116 loc) · 4.07 KB
/
llc_cpuwise_histogram.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/usr/bin/python
#
from __future__ import print_function
import argparse
from bcc import BPF, PerfType, PerfHWConfig
import signal
from time import sleep
import json
parser = argparse.ArgumentParser(
description="Summarize cache references and misses by PID",
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument(
"-c", "--sample_period", type=int, default=100,
help="Sample one in this many number of cache reference / miss events")
parser.add_argument(
"duration", nargs="?", default=10, help="Duration, in seconds, to run")
parser.add_argument("--ebpf", action="store_true",
help=argparse.SUPPRESS)
parser.add_argument("-p", "--plot", action="store_true", help="Plot bar plot")
parser.add_argument("-l", "--load", action="store_true", help="Load Previous Run Data")
args = parser.parse_args()
# load BPF program
bpf_text="""
#include <linux/ptrace.h>
#include <uapi/linux/bpf_perf_event.h>
BPF_HISTOGRAM(ref_count, u32);
BPF_HISTOGRAM(miss_count, u32);
int on_cache_miss(struct bpf_perf_event_data *ctx) {
u32 cpu = bpf_get_smp_processor_id();
miss_count.increment(cpu, ctx->sample_period);
return 0;
}
int on_cache_ref(struct bpf_perf_event_data *ctx) {
u32 cpu = bpf_get_smp_processor_id();
ref_count.increment(cpu, ctx->sample_period);
return 0;
}
"""
if args.ebpf:
print(bpf_text)
exit()
b = BPF(text=bpf_text)
try:
b.attach_perf_event(
ev_type=PerfType.HARDWARE, ev_config=PerfHWConfig.CACHE_MISSES,
fn_name="on_cache_miss", sample_period=args.sample_period)
b.attach_perf_event(
ev_type=PerfType.HARDWARE, ev_config=PerfHWConfig.CACHE_REFERENCES,
fn_name="on_cache_ref", sample_period=args.sample_period)
except Exception:
print("Failed to attach to a hardware event. Is this a virtual machine?")
exit()
print("Running for {} seconds or hit Ctrl-C to end.".format(args.duration))
try:
sleep(float(args.duration))
except KeyboardInterrupt:
signal.signal(signal.SIGINT, lambda signal, frame: print())
print("-" * 32)
print("Miss Count Histogram")
b["miss_count"].print_linear_hist(val_type="CPU")
print("-" * 32)
print("Ref Count Histogram")
b["ref_count"].print_linear_hist(val_type="CPU")
miss = b.get_table("miss_count")
refs = b.get_table("ref_count")
hit_rate = {}
miss_rate = {}
for (k, v) in refs.items():
total = v.value + miss[k].value
hit_rate[k.value] = 1.0 * v.value / total
miss_rate[k.value] = 1.0 * miss[k].value / total
print("-" * 32)
print("Hit/Miss Rate")
print("%-8s %-8s %s" % ("CPU", "HitRate", "MissRate"))
for cpu in hit_rate:
print("%-8s %-8.2f %.2f" % (cpu, hit_rate[cpu], miss_rate[cpu]))
if args.plot:
print("Plotting Bar Chart")
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
if args.load:
print("Loading prev.json")
with open('prev.json', 'r') as f:
data = f.read()
[prev_hit, prev_miss] = json.loads(data)
x_labels = []
hit_data = []
miss_data = []
prev_hit_data = []
prev_miss_data = []
for cpu in hit_rate:
x_labels.append('CPU' + str(cpu))
hit_data.append(hit_rate[cpu])
miss_data.append(miss_rate[cpu])
if args.load:
prev_hit_data.append(prev_hit[str(cpu)])
prev_miss_data.append(prev_miss[str(cpu)])
width = 0.25
x = np.arange(len(x_labels))
fig, ax = plt.subplots()
ax.bar(x - width / 2, hit_data, width = width, label = 'CurrentHitRate', tick_label=x_labels)
ax.bar(x - width / 2, miss_data, width = width, bottom=hit_data, label = 'CurrentMissRate')
if args.load:
ax.bar(x + width / 2, prev_hit_data, width = width, label = 'PreviousHitRate')
ax.bar(x + width / 2, prev_miss_data, width = width, bottom=prev_hit_data, label = 'PreviousMissRate')
ax.set_ylabel('Hit/Miss Rate%')
ax.set_title('LLC Hit Ratio')
ax.set(ylim=(0.0,1.2))
ax.legend()
plt.show()
f = open('prev.json', 'w')
print("Dumping Current Run Data in prev.json.To load use -l flag")
f.write(json.dumps([hit_rate, miss_rate]))
f.flush()
f.close()