rbbcc 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/README.md +4 -0
- data/docs/README.md +2 -0
- data/docs/answers/01-hello-world.rb +16 -0
- data/docs/answers/02-sys_sync.rb +18 -0
- data/docs/answers/03-hello_fields.rb +33 -0
- data/docs/answers/04-sync_timing.rb +46 -0
- data/docs/answers/05-sync_count.rb +54 -0
- data/docs/answers/06-disksnoop.rb +71 -0
- data/docs/answers/07-hello_perf_output.rb +59 -0
- data/docs/answers/08-sync_perf_output.rb +60 -0
- data/docs/answers/09-bitehist.rb +32 -0
- data/docs/answers/10-disklatency.rb +51 -0
- data/docs/answers/11-vfsreadlat.c +46 -0
- data/docs/answers/11-vfsreadlat.rb +66 -0
- data/docs/answers/12-urandomread.rb +38 -0
- data/docs/answers/13-disksnoop_fixed.rb +108 -0
- data/docs/answers/14-strlen_count.rb +46 -0
- data/docs/answers/15-nodejs_http_server.rb +44 -0
- data/docs/answers/16-task_switch.c +23 -0
- data/docs/answers/16-task_switch.rb +17 -0
- data/docs/answers/node-server.js +11 -0
- data/docs/projects_using_rbbcc.md +43 -0
- data/docs/tutorial_bcc_ruby_developer.md +772 -0
- data/lib/rbbcc/bcc.rb +41 -13
- data/lib/rbbcc/clib.rb +1 -0
- data/lib/rbbcc/table.rb +16 -22
- data/lib/rbbcc/version.rb +1 -1
- data/rbbcc.gemspec +1 -1
- metadata +25 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 35d11d74dd0d8eacf88978ec066ede1d64aef374027d819f5891a124822db4e9
|
4
|
+
data.tar.gz: 22125362cf25181c33b253d7c6ece7d2e9b9fa2d8933d8c7f120c453384df5d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d145f5307df79f42679892b26b4f3f320dbdfb7d931f65f9f2b84ba4032d780991c2f2d0fb36a06b030bc59e45d16b4cca201d42e0368eb5ed4d4853958d44f3
|
7
|
+
data.tar.gz: 86c50507da5cc6ba947def8ce7c169937a432579ce92e0b70c0d24d4316fbba7c45a2de22d602b0c166f473db8e8fddeab1d961b07b97dd719b0a30f15fd9234
|
data/Gemfile.lock
CHANGED
@@ -12,7 +12,7 @@ GEM
|
|
12
12
|
pry (0.12.2)
|
13
13
|
coderay (~> 1.1.0)
|
14
14
|
method_source (~> 0.9.0)
|
15
|
-
rake (
|
15
|
+
rake (13.0.1)
|
16
16
|
|
17
17
|
PLATFORMS
|
18
18
|
ruby
|
@@ -21,7 +21,7 @@ DEPENDENCIES
|
|
21
21
|
bundler (~> 2.0)
|
22
22
|
minitest
|
23
23
|
pry
|
24
|
-
rake (~>
|
24
|
+
rake (~> 13.0)
|
25
25
|
rbbcc!
|
26
26
|
|
27
27
|
BUNDLED WITH
|
data/README.md
CHANGED
@@ -94,6 +94,10 @@ $ docker run --privileged \
|
|
94
94
|
runc-5025 [003] d... 1237.797464: : Hello, World!
|
95
95
|
```
|
96
96
|
|
97
|
+
## Documents
|
98
|
+
|
99
|
+
See [docs/](docs/) for getting started and tutorial.
|
100
|
+
|
97
101
|
## Development
|
98
102
|
|
99
103
|
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/docs/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# RbBCC Docs
|
2
2
|
|
3
3
|
* [Getting Started](getting_started.md)
|
4
|
+
* [Ruby Tutorial](tutorial_bcc_ruby_developer.md)
|
5
|
+
* [Projects Using RbBCC](projects_using_rbbcc.md)
|
4
6
|
|
5
7
|
**Please see also [BCC itself's README](https://github.com/iovisor/bcc/#readme) and [docs](https://github.com/iovisor/bcc/tree/master/docs).**
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Original hello_world.py:
|
3
|
+
# Copyright (c) PLUMgrid, Inc.
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License")
|
5
|
+
#
|
6
|
+
# This Ruby version follows the Apache License 2.0
|
7
|
+
|
8
|
+
# run in project examples directory with:
|
9
|
+
# sudo ./hello_world.rb"
|
10
|
+
# see trace_fields.rb for a longer example
|
11
|
+
|
12
|
+
require "rbbcc"
|
13
|
+
include RbBCC
|
14
|
+
|
15
|
+
# This may not work for 4.17 on x64, you need replace kprobe__sys_clone with kprobe____x64_sys_clone
|
16
|
+
BCC.new(text: 'int kprobe__sys_clone(void *ctx) { bpf_trace_printk("Hello, World!\\n"); return 0; }').trace_print
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Licensed under the Apache License, Version 2.0 (the "License")
|
3
|
+
|
4
|
+
require "rbbcc"
|
5
|
+
include RbBCC
|
6
|
+
|
7
|
+
puts "Tracing sys_sync()... Ctrl-C to end."
|
8
|
+
begin
|
9
|
+
BCC.new(text: <<~BPF).trace_print
|
10
|
+
int kprobe__sys_sync(void *ctx) {
|
11
|
+
bpf_trace_printk("sys_sync() called\\n");
|
12
|
+
return 0;
|
13
|
+
}
|
14
|
+
BPF
|
15
|
+
rescue Interrupt
|
16
|
+
puts
|
17
|
+
puts "Done"
|
18
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Licensed under the Apache License, Version 2.0 (the "License")
|
3
|
+
|
4
|
+
require "rbbcc"
|
5
|
+
include RbBCC
|
6
|
+
|
7
|
+
# define BPF program
|
8
|
+
prog = <<BPF
|
9
|
+
int hello(void *ctx) {
|
10
|
+
bpf_trace_printk("Hello, World!\\n");
|
11
|
+
return 0;
|
12
|
+
}
|
13
|
+
BPF
|
14
|
+
|
15
|
+
# load BPF program
|
16
|
+
b = BCC.new(text: prog)
|
17
|
+
b.attach_kprobe(event: b.get_syscall_fnname("clone"), fn_name: "hello")
|
18
|
+
|
19
|
+
# header
|
20
|
+
puts("%-18s %-16s %-6s %s" % ["TIME(s)", "COMM", "PID", "MESSAGE"])
|
21
|
+
|
22
|
+
# format output
|
23
|
+
begin
|
24
|
+
b.trace_fields do |task, pid, cpu, flags, ts, msg|
|
25
|
+
print("%-18.9f %-16s %-6d %s" % [ts, task, pid, msg])
|
26
|
+
end
|
27
|
+
rescue Interrupt
|
28
|
+
puts
|
29
|
+
puts "Done"
|
30
|
+
rescue => e
|
31
|
+
p e
|
32
|
+
retry
|
33
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Original sync_timing.py:
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License")
|
4
|
+
#
|
5
|
+
# This Ruby version follows the Apache License 2.0
|
6
|
+
|
7
|
+
require "rbbcc"
|
8
|
+
include RbBCC
|
9
|
+
|
10
|
+
# load BPF program
|
11
|
+
b = BCC.new(text: <<BPF)
|
12
|
+
#include <uapi/linux/ptrace.h>
|
13
|
+
|
14
|
+
BPF_HASH(last);
|
15
|
+
|
16
|
+
int do_trace(struct pt_regs *ctx) {
|
17
|
+
u64 ts, *tsp, delta, key = 0;
|
18
|
+
|
19
|
+
// attempt to read stored timestamp
|
20
|
+
tsp = last.lookup(&key);
|
21
|
+
if (tsp != 0) {
|
22
|
+
delta = bpf_ktime_get_ns() - *tsp;
|
23
|
+
if (delta < 1000000000) {
|
24
|
+
// output if time is less than 1 second
|
25
|
+
bpf_trace_printk("%d\\n", delta / 1000000);
|
26
|
+
}
|
27
|
+
last.delete(&key);
|
28
|
+
}
|
29
|
+
|
30
|
+
// update stored timestamp
|
31
|
+
ts = bpf_ktime_get_ns();
|
32
|
+
last.update(&key, &ts);
|
33
|
+
return 0;
|
34
|
+
}
|
35
|
+
BPF
|
36
|
+
|
37
|
+
b.attach_kprobe(event: b.get_syscall_fnname("sync"), fn_name: "do_trace")
|
38
|
+
puts("Tracing for quick sync's... Ctrl-C to end")
|
39
|
+
|
40
|
+
# format output
|
41
|
+
start = 0
|
42
|
+
b.trace_fields do |task, pid, cpu, flags, ts, ms|
|
43
|
+
start = ts.to_f if start.zero?
|
44
|
+
ts = ts.to_f - start
|
45
|
+
puts("At time %.2f s: multiple syncs detected, last %s ms ago" % [ts, ms.chomp])
|
46
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Licensed under the Apache License, Version 2.0 (the "License")
|
3
|
+
|
4
|
+
require "rbbcc"
|
5
|
+
include RbBCC
|
6
|
+
|
7
|
+
# load BPF program
|
8
|
+
b = BCC.new(text: <<BPF)
|
9
|
+
#include <uapi/linux/ptrace.h>
|
10
|
+
|
11
|
+
BPF_HASH(last);
|
12
|
+
|
13
|
+
int do_trace(struct pt_regs *ctx) {
|
14
|
+
u64 ts, *tsp, delta, key = 0, counter_key = 1, zero = 0;
|
15
|
+
|
16
|
+
// initialize counter key
|
17
|
+
if (last.lookup_or_try_init(&counter_key, &zero))
|
18
|
+
last.increment(counter_key);
|
19
|
+
|
20
|
+
// attempt to read stored timestamp
|
21
|
+
tsp = last.lookup(&key);
|
22
|
+
if (tsp != 0) {
|
23
|
+
delta = bpf_ktime_get_ns() - *tsp;
|
24
|
+
if (delta < 1000000000) {
|
25
|
+
// output if time is less than 1 second
|
26
|
+
bpf_trace_printk("%d\\n", delta / 1000000);
|
27
|
+
}
|
28
|
+
last.delete(&key);
|
29
|
+
}
|
30
|
+
|
31
|
+
// update stored timestamp
|
32
|
+
ts = bpf_ktime_get_ns();
|
33
|
+
last.update(&key, &ts);
|
34
|
+
return 0;
|
35
|
+
}
|
36
|
+
BPF
|
37
|
+
|
38
|
+
COUNTER_KEY = 1
|
39
|
+
|
40
|
+
b.attach_kprobe(event: b.get_syscall_fnname("sync"), fn_name: "do_trace")
|
41
|
+
puts("Tracing for quick sync's... Ctrl-C to end")
|
42
|
+
|
43
|
+
# format output
|
44
|
+
start = 0
|
45
|
+
begin
|
46
|
+
b.trace_fields do |task, pid, cpu, flags, ts, ms|
|
47
|
+
start = ts.to_f if start.zero?
|
48
|
+
ts = ts.to_f - start
|
49
|
+
puts("At time %.2f s: multiple syncs detected, last %s ms ago" % [ts, ms.chomp])
|
50
|
+
end
|
51
|
+
rescue Interrupt
|
52
|
+
table = b["last"]
|
53
|
+
puts "Count of sys_sync: %d" % table[COUNTER_KEY].to_bcc_value
|
54
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# disksnoop.rb Trace block device I/O: basic version of iosnoop.
|
4
|
+
# For Linux, uses BCC, eBPF. Embedded C.
|
5
|
+
# This is ported from original disksnoop.py
|
6
|
+
#
|
7
|
+
# Written as a basic example of tracing latency.
|
8
|
+
#
|
9
|
+
# Licensed under the Apache License, Version 2.0 (the "License")
|
10
|
+
#
|
11
|
+
# 11-Aug-2015 Brendan Gregg Created disksnoop.py
|
12
|
+
|
13
|
+
require 'rbbcc'
|
14
|
+
include RbBCC
|
15
|
+
|
16
|
+
REQ_WRITE = 1 # from include/linux/blk_types.h
|
17
|
+
|
18
|
+
# load BPF program
|
19
|
+
b = BCC.new(text: <<CLANG)
|
20
|
+
#include <uapi/linux/ptrace.h>
|
21
|
+
#include <linux/blkdev.h>
|
22
|
+
|
23
|
+
BPF_HASH(start, struct request *);
|
24
|
+
|
25
|
+
void trace_start(struct pt_regs *ctx, struct request *req) {
|
26
|
+
// stash start timestamp by request ptr
|
27
|
+
u64 ts = bpf_ktime_get_ns();
|
28
|
+
|
29
|
+
start.update(&req, &ts);
|
30
|
+
}
|
31
|
+
|
32
|
+
void trace_completion(struct pt_regs *ctx, struct request *req) {
|
33
|
+
u64 *tsp, delta;
|
34
|
+
|
35
|
+
tsp = start.lookup(&req);
|
36
|
+
if (tsp != 0) {
|
37
|
+
delta = bpf_ktime_get_ns() - *tsp;
|
38
|
+
bpf_trace_printk("%d %x %d\\n", req->__data_len,
|
39
|
+
req->cmd_flags, delta / 1000);
|
40
|
+
start.delete(&req);
|
41
|
+
}
|
42
|
+
}
|
43
|
+
CLANG
|
44
|
+
|
45
|
+
b.attach_kprobe(event: "blk_start_request", fn_name: "trace_start") if BCC.get_kprobe_functions('blk_start_request')
|
46
|
+
b.attach_kprobe(event: "blk_mq_start_request", fn_name: "trace_start")
|
47
|
+
b.attach_kprobe(event: "blk_account_io_completion", fn_name: "trace_completion")
|
48
|
+
|
49
|
+
# header
|
50
|
+
puts("%-18s %-2s %-7s %8s" % ["TIME(s)", "T", "BYTES", "LAT(ms)"])
|
51
|
+
|
52
|
+
# format output
|
53
|
+
loop do
|
54
|
+
begin
|
55
|
+
task, pid, cpu, flags, ts, msg = b.trace_fields
|
56
|
+
bytes_s, bflags_s, us_s = msg.split
|
57
|
+
|
58
|
+
if (bflags_s.to_i(16) & REQ_WRITE).nonzero?
|
59
|
+
type_s = "W"
|
60
|
+
elsif bytes_s == "0" # see blk_fill_rwbs() for logic
|
61
|
+
type_s = "M"
|
62
|
+
else
|
63
|
+
type_s = "R"
|
64
|
+
end
|
65
|
+
ms = us_s.to_i.to_f / 1000
|
66
|
+
|
67
|
+
puts("%-18.9f %-2s %-7s %8.2f" % [ts, type_s, bytes_s, ms])
|
68
|
+
rescue Interrupt
|
69
|
+
exit
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This is a Hello World example that uses BPF_PERF_OUTPUT.
|
4
|
+
# Ported from hello_perf_output.py
|
5
|
+
|
6
|
+
require 'rbbcc'
|
7
|
+
include RbBCC
|
8
|
+
|
9
|
+
# define BPF program
|
10
|
+
prog = """
|
11
|
+
#include <linux/sched.h>
|
12
|
+
|
13
|
+
// define output data structure in C
|
14
|
+
struct data_t {
|
15
|
+
u32 pid;
|
16
|
+
u64 ts;
|
17
|
+
char comm[TASK_COMM_LEN];
|
18
|
+
};
|
19
|
+
BPF_PERF_OUTPUT(events);
|
20
|
+
|
21
|
+
int hello(struct pt_regs *ctx) {
|
22
|
+
struct data_t data = {};
|
23
|
+
|
24
|
+
data.pid = bpf_get_current_pid_tgid();
|
25
|
+
data.ts = bpf_ktime_get_ns();
|
26
|
+
bpf_get_current_comm(&data.comm, sizeof(data.comm));
|
27
|
+
|
28
|
+
events.perf_submit(ctx, &data, sizeof(data));
|
29
|
+
|
30
|
+
return 0;
|
31
|
+
}
|
32
|
+
"""
|
33
|
+
|
34
|
+
# load BPF program
|
35
|
+
b = BCC.new(text: prog)
|
36
|
+
b.attach_kprobe(event: b.get_syscall_fnname("clone"), fn_name: "hello")
|
37
|
+
|
38
|
+
# header
|
39
|
+
puts("%-18s %-16s %-6s %s" % ["TIME(s)", "COMM", "PID", "MESSAGE"])
|
40
|
+
|
41
|
+
# process event
|
42
|
+
start = 0
|
43
|
+
print_event = lambda { |cpu, data, size|
|
44
|
+
event = b["events"].event(data)
|
45
|
+
if start == 0
|
46
|
+
start = event.ts
|
47
|
+
end
|
48
|
+
|
49
|
+
time_s = ((event.ts - start).to_f) / 1000000000
|
50
|
+
puts("%-18.9f %-16s %-6d %s" % [time_s, event.comm, event.pid,
|
51
|
+
"Hello, perf_output!"])
|
52
|
+
}
|
53
|
+
|
54
|
+
# loop with callback to print_event
|
55
|
+
b["events"].open_perf_buffer(&print_event)
|
56
|
+
|
57
|
+
loop do
|
58
|
+
b.perf_buffer_poll()
|
59
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Licensed under the Apache License, Version 2.0 (the "License")
|
3
|
+
|
4
|
+
require "rbbcc"
|
5
|
+
include RbBCC
|
6
|
+
|
7
|
+
# load BPF program
|
8
|
+
b = BCC.new(text: <<BPF)
|
9
|
+
#include <uapi/linux/ptrace.h>
|
10
|
+
|
11
|
+
struct data_t {
|
12
|
+
u32 pid;
|
13
|
+
u64 ts;
|
14
|
+
u64 delta;
|
15
|
+
};
|
16
|
+
BPF_PERF_OUTPUT(events);
|
17
|
+
BPF_HASH(last);
|
18
|
+
|
19
|
+
int do_trace(struct pt_regs *ctx) {
|
20
|
+
u64 ts, *tsp, delta, key = 0;
|
21
|
+
|
22
|
+
// attempt to read stored timestamp
|
23
|
+
tsp = last.lookup(&key);
|
24
|
+
if (tsp != 0) {
|
25
|
+
struct data_t data = {};
|
26
|
+
delta = bpf_ktime_get_ns() - *tsp;
|
27
|
+
if (delta < 1000000000) {
|
28
|
+
data.pid = bpf_get_current_pid_tgid();
|
29
|
+
data.ts = bpf_ktime_get_ns();
|
30
|
+
data.delta = delta;
|
31
|
+
events.perf_submit(ctx, &data, sizeof(data));
|
32
|
+
}
|
33
|
+
last.delete(&key);
|
34
|
+
}
|
35
|
+
|
36
|
+
// update stored timestamp
|
37
|
+
ts = bpf_ktime_get_ns();
|
38
|
+
last.update(&key, &ts);
|
39
|
+
return 0;
|
40
|
+
}
|
41
|
+
BPF
|
42
|
+
|
43
|
+
b.attach_kprobe(event: b.get_syscall_fnname("sync"), fn_name: "do_trace")
|
44
|
+
puts("Tracing for quick sync's... Ctrl-C to end")
|
45
|
+
|
46
|
+
# format output
|
47
|
+
start = 0
|
48
|
+
b["events"].open_perf_buffer do |_, data, _|
|
49
|
+
event = b["events"].event(data)
|
50
|
+
if start == 0
|
51
|
+
start = event.ts
|
52
|
+
end
|
53
|
+
|
54
|
+
time_s = ((event.ts - start).to_f) / 1_000_000_000
|
55
|
+
puts("At time %.2f s: multiple syncs detected, last %s ms ago" % [time_s, event.delta / 1_000_000])
|
56
|
+
end
|
57
|
+
|
58
|
+
loop do
|
59
|
+
b.perf_buffer_poll()
|
60
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Licensed under the Apache License, Version 2.0 (the "License")
|
3
|
+
|
4
|
+
require 'rbbcc'
|
5
|
+
include RbBCC
|
6
|
+
|
7
|
+
# load BPF program
|
8
|
+
b = BCC.new(text: <<BPF)
|
9
|
+
#include <uapi/linux/ptrace.h>
|
10
|
+
#include <linux/blkdev.h>
|
11
|
+
|
12
|
+
BPF_HISTOGRAM(dist);
|
13
|
+
|
14
|
+
int kprobe__blk_account_io_completion(struct pt_regs *ctx, struct request *req)
|
15
|
+
{
|
16
|
+
dist.increment(bpf_log2l(req->__data_len / 1024));
|
17
|
+
return 0;
|
18
|
+
}
|
19
|
+
BPF
|
20
|
+
|
21
|
+
# header
|
22
|
+
puts("Tracing... Hit Ctrl-C to end.")
|
23
|
+
|
24
|
+
# trace until Ctrl-C
|
25
|
+
begin
|
26
|
+
loop { sleep 0.1 }
|
27
|
+
rescue Interrupt
|
28
|
+
puts
|
29
|
+
end
|
30
|
+
|
31
|
+
# output
|
32
|
+
b["dist"].print_log2_hist("kbytes")
|
@@ -0,0 +1,51 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Licensed under the Apache License, Version 2.0 (the "License")
|
3
|
+
|
4
|
+
require 'rbbcc'
|
5
|
+
include RbBCC
|
6
|
+
|
7
|
+
b = BCC.new(text: <<BPF)
|
8
|
+
#include <uapi/linux/ptrace.h>
|
9
|
+
#include <linux/blkdev.h>
|
10
|
+
|
11
|
+
BPF_HASH(start, struct request *);
|
12
|
+
BPF_HISTOGRAM(dist);
|
13
|
+
|
14
|
+
// note this program mixes R/W
|
15
|
+
// For next step, handle req->cmd_flags and prepare hist hash per op.
|
16
|
+
|
17
|
+
void trace_start(struct pt_regs *ctx, struct request *req) {
|
18
|
+
// stash start timestamp by request ptr
|
19
|
+
u64 ts = bpf_ktime_get_ns();
|
20
|
+
|
21
|
+
start.update(&req, &ts);
|
22
|
+
}
|
23
|
+
|
24
|
+
void trace_completion(struct pt_regs *ctx, struct request *req) {
|
25
|
+
u64 *tsp, delta;
|
26
|
+
|
27
|
+
tsp = start.lookup(&req);
|
28
|
+
if (tsp != 0) {
|
29
|
+
delta = bpf_ktime_get_ns() - *tsp;
|
30
|
+
dist.increment(bpf_log2l(delta / 1000)); // us
|
31
|
+
start.delete(&req);
|
32
|
+
}
|
33
|
+
}
|
34
|
+
BPF
|
35
|
+
|
36
|
+
b.attach_kprobe(event: "blk_start_request", fn_name: "trace_start") if BCC.get_kprobe_functions('blk_start_request')
|
37
|
+
b.attach_kprobe(event: "blk_mq_start_request", fn_name: "trace_start")
|
38
|
+
b.attach_kprobe(event: "blk_account_io_completion", fn_name: "trace_completion")
|
39
|
+
|
40
|
+
# header
|
41
|
+
puts("Tracing... Hit Ctrl-C to end.")
|
42
|
+
|
43
|
+
# trace until Ctrl-C
|
44
|
+
begin
|
45
|
+
loop { sleep 0.1 }
|
46
|
+
rescue Interrupt
|
47
|
+
puts
|
48
|
+
end
|
49
|
+
|
50
|
+
# output
|
51
|
+
b["dist"].print_log2_hist("usec")
|
@@ -0,0 +1,46 @@
|
|
1
|
+
/*
|
2
|
+
* From: https://github.com/iovisor/bcc/blob/master/examples/tracing/vfsreadlat.c
|
3
|
+
*
|
4
|
+
* vfsreadlat.c VFS read latency distribution.
|
5
|
+
* For Linux, uses BCC, eBPF. See .py/.rb file.
|
6
|
+
*
|
7
|
+
* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com
|
8
|
+
* This program is free software; you can redistribute it and/or
|
9
|
+
* modify it under the terms of version 2 of the GNU General Public
|
10
|
+
* License as published by the Free Software Foundation.
|
11
|
+
*
|
12
|
+
* 15-Aug-2015 Brendan Gregg Created this.
|
13
|
+
*/
|
14
|
+
|
15
|
+
#include <uapi/linux/ptrace.h>
|
16
|
+
|
17
|
+
BPF_HASH(start, u32);
|
18
|
+
BPF_HISTOGRAM(dist);
|
19
|
+
|
20
|
+
int do_entry(struct pt_regs *ctx)
|
21
|
+
{
|
22
|
+
u32 pid;
|
23
|
+
u64 ts, *val;
|
24
|
+
|
25
|
+
pid = bpf_get_current_pid_tgid();
|
26
|
+
ts = bpf_ktime_get_ns();
|
27
|
+
start.update(&pid, &ts);
|
28
|
+
return 0;
|
29
|
+
}
|
30
|
+
|
31
|
+
int do_return(struct pt_regs *ctx)
|
32
|
+
{
|
33
|
+
u32 pid;
|
34
|
+
u64 *tsp, delta;
|
35
|
+
|
36
|
+
pid = bpf_get_current_pid_tgid();
|
37
|
+
tsp = start.lookup(&pid);
|
38
|
+
|
39
|
+
if (tsp != 0) {
|
40
|
+
delta = bpf_ktime_get_ns() - *tsp;
|
41
|
+
dist.increment(bpf_log2l(delta / 1000));
|
42
|
+
start.delete(&pid);
|
43
|
+
}
|
44
|
+
|
45
|
+
return 0;
|
46
|
+
}
|
@@ -0,0 +1,66 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Original: from vfsreadlat.py
|
4
|
+
# Copyright (c) 2015 Brendan Gregg.
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License")
|
6
|
+
# Ruby version follows.
|
7
|
+
#
|
8
|
+
# vfsreadlat.rb VFS read latency distribution.
|
9
|
+
# For Linux, uses BCC, eBPF. See .c file.
|
10
|
+
#
|
11
|
+
# Written as a basic example of a function latency distribution histogram.
|
12
|
+
#
|
13
|
+
# USAGE: vfsreadlat.rb [interval [count]]
|
14
|
+
#
|
15
|
+
# The default interval is 5 seconds. A Ctrl-C will print the partially
|
16
|
+
# gathered histogram then exit.
|
17
|
+
|
18
|
+
require "rbbcc"
|
19
|
+
include RbBCC
|
20
|
+
|
21
|
+
def usage
|
22
|
+
puts("USAGE: %s [interval [count]]" % $0)
|
23
|
+
exit
|
24
|
+
end
|
25
|
+
|
26
|
+
# arguments
|
27
|
+
interval = 5
|
28
|
+
count = -1
|
29
|
+
if ARGV.size > 0
|
30
|
+
begin
|
31
|
+
interval = ARGV[0].to_i
|
32
|
+
raise if interval == 0
|
33
|
+
count = ARGV[1].to_i if ARGV[1]
|
34
|
+
rescue => e # also catches -h, --help
|
35
|
+
usage()
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# load BPF program
|
40
|
+
b = BCC.new(src_file: "11-vfsreadlat.c")
|
41
|
+
b.attach_kprobe(event: "vfs_read", fn_name: "do_entry")
|
42
|
+
b.attach_kretprobe(event: "vfs_read", fn_name: "do_return")
|
43
|
+
|
44
|
+
# header
|
45
|
+
print("Tracing... Hit Ctrl-C to end.")
|
46
|
+
|
47
|
+
# output
|
48
|
+
cycle = 0
|
49
|
+
do_exit = false
|
50
|
+
loop do
|
51
|
+
if count > 0
|
52
|
+
cycle += 1
|
53
|
+
exit if cycle > count
|
54
|
+
end
|
55
|
+
|
56
|
+
begin
|
57
|
+
sleep(interval)
|
58
|
+
rescue Interrupt
|
59
|
+
do_exit = true
|
60
|
+
end
|
61
|
+
|
62
|
+
puts
|
63
|
+
b["dist"].print_log2_hist("usecs")
|
64
|
+
b["dist"].clear
|
65
|
+
exit if do_exit
|
66
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# urandomread.rb Example of instrumenting a kernel tracepoint.
|
4
|
+
# For Linux, uses BCC, BPF. Embedded C.
|
5
|
+
#
|
6
|
+
# REQUIRES: Linux 4.7+ (BPF_PROG_TYPE_TRACEPOINT support).
|
7
|
+
#
|
8
|
+
# Test by running this, then in another shell, run:
|
9
|
+
# dd if=/dev/urandom of=/dev/null bs=1k count=5
|
10
|
+
#
|
11
|
+
# Original urandomread.py Copyright 2016 Netflix, Inc.
|
12
|
+
# Licensed under the Apache License, Version 2.0 (the "License")
|
13
|
+
# Ruby version follows.
|
14
|
+
|
15
|
+
require 'rbbcc'
|
16
|
+
include RbBCC
|
17
|
+
|
18
|
+
b = BCC.new(text: <<BPF)
|
19
|
+
TRACEPOINT_PROBE(random, urandom_read) {
|
20
|
+
// args is from /sys/kernel/debug/tracing/events/random/urandom_read/format
|
21
|
+
bpf_trace_printk("%d\\n", args->got_bits);
|
22
|
+
return 0;
|
23
|
+
}
|
24
|
+
BPF
|
25
|
+
|
26
|
+
# header
|
27
|
+
puts("%-18s %-16s %-6s %s" % ["TIME(s)", "COMM", "PID", "GOTBITS"])
|
28
|
+
|
29
|
+
# format output
|
30
|
+
loop do
|
31
|
+
begin
|
32
|
+
b.trace_fields do |task, pid, cpu, flags, ts, msg|
|
33
|
+
puts("%-18.9f %-16s %-6d %s" % [ts, task, pid, msg])
|
34
|
+
end
|
35
|
+
rescue Interrupt
|
36
|
+
exit
|
37
|
+
end
|
38
|
+
end
|