-
Notifications
You must be signed in to change notification settings - Fork 0
/
concurrency_monitor.bt
executable file
·72 lines (64 loc) · 1.71 KB
/
concurrency_monitor.bt
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
#!/usr/bin/env bpftrace
// based on ../../really_dumb_concurrency_monitor.bt
// This version ignores potential concurrency issues
#define MAX_CPU 256
#define IGNORE_IDLE 0
#define NANOS_PER_MILLE ((uint64) (1e6*$1/1000))
// stupid way to find number of CPUs
profile:hz:2
{
@last_cpu = cpu > @last_cpu ? cpu : @last_cpu;
}
// 650 ns total average runtime, but only 62 ns under CPU saturation
tracepoint:sched:sched_switch
/ (args.prev_pid & args.next_pid) == 0 / // equiv prev == 0 || next == 0
{
if (@last_event) {
// count active CPUs during last period
$n_active = 0;
$cpu = 0;
while ($cpu < MAX_CPU) {
$n_active += @cpu_awake[$cpu];
++$cpu;
if ($cpu > @last_cpu) {
break;
}
}
@concurrency[$n_active] = sum(nsecs - @last_event);
}
@last_event = nsecs;
// register whether we are awake in the next period
@cpu_awake[cpu] = args.next_pid ? 1 : 0;
}
interval:ms:$1
{
// Run the accounting loop once, just in case of 100% cpu saturation
if (@last_event) {
// count active CPUs during last period
$n_active = 0;
$cpu = 0;
while ($cpu < MAX_CPU) {
$n_active += @cpu_awake[$cpu];
++$cpu;
if ($cpu > @last_cpu) {
break;
}
}
@concurrency[$n_active] = sum(nsecs - @last_event);
}
@last_event = nsecs; //synthetic, but that's okay!
// Show stats
printf("Concurrency per mille\n");
$i = 0;
while ($i < MAX_CPU+1) {
$awake_nanos = 0 + @concurrency[$i];
$awake_per_mille = ($awake_nanos - @awake_nanos_last[$i]) / NANOS_PER_MILLE;
@awake_nanos_last[$i] = $awake_nanos;
printf("%3d : %4d\n", $i, $awake_per_mille);
// loop counter
++$i;
if ($i > @last_cpu+1) {
break;
}
}
}