|
| 1 | +use std::sync::atomic::AtomicU8; |
| 2 | + |
| 3 | +pub const LABELS_LEN: usize = 4096; |
| 4 | + |
| 5 | +/// Shared-memory array indexed by `tid % LABELS_LEN`. |
| 6 | +/// |
| 7 | +/// Rust writes the component's group ID on enter and 0 on exit (~1ns, no kernel |
| 8 | +/// involvement). bpftrace reads this array on a fixed-rate profile timer |
| 9 | +/// (`profile:hz:997`) to attribute stack samples to components. |
| 10 | +/// |
| 11 | +/// 4096 entries = 4KB. TID collision requires two Vector threads whose TIDs |
| 12 | +/// differ by exactly 4096 — effectively impossible for a process with ~8-32 |
| 13 | +/// threads. |
| 14 | +#[no_mangle] |
| 15 | +pub static VECTOR_COMPONENT_LABELS: [AtomicU8; LABELS_LEN] = { |
| 16 | + const ZERO: AtomicU8 = AtomicU8::new(0); |
| 17 | + [ZERO; LABELS_LEN] |
| 18 | +}; |
| 19 | + |
1 | 20 | /// Uprobe attachment point: called once per component at startup to register |
2 | 21 | /// the mapping from allocation group ID to component name. |
3 | 22 | /// |
4 | 23 | /// bpftrace attaches `uprobe:BINARY:vector_register_component` here at probe |
5 | | -/// startup to build a `group_id → component_id` lookup table. At sample time, |
6 | | -/// bpftrace reads the thread-local allocation group stack to get the current |
7 | | -/// group ID and looks it up in that table. |
| 24 | +/// startup to build a `group_id -> component_id` lookup table. It also |
| 25 | +/// captures `labels_ptr` / `labels_len` on the first call so the profile |
| 26 | +/// handler can read the shared-memory array at runtime (ASLR makes the |
| 27 | +/// compile-time address unusable). |
8 | 28 | /// |
9 | 29 | /// Arguments follow the C ABI so bpftrace can read them reliably: |
10 | 30 | /// arg0 = group_id (u8) |
11 | 31 | /// arg1/arg2 = component_id (ptr, len) |
| 32 | +/// arg3/arg4 = labels array (ptr, len) |
12 | 33 | /// |
13 | 34 | /// `black_box` prevents LTO from eliding the call site. |
14 | 35 | #[no_mangle] |
15 | 36 | #[inline(never)] |
16 | | -pub extern "C" fn vector_register_component(id: u8, name_ptr: *const u8, name_len: usize) { |
17 | | - std::hint::black_box((id, name_ptr, name_len)); |
18 | | -} |
19 | | - |
20 | | -/// Uprobe attachment point: called on every allocation group enter (i.e. every Tokio task poll |
21 | | -/// that enters a component's group). bpftrace attaches here to record the active component ID |
22 | | -/// on the current thread without needing span machinery. |
23 | | -/// |
24 | | -/// Arguments follow the C ABI so bpftrace can read them reliably: |
25 | | -/// arg0 = group_id (u8) |
26 | | -#[no_mangle] |
27 | | -#[inline(never)] |
28 | | -pub extern "C" fn vector_component_enter(id: u8) { |
29 | | - std::hint::black_box(id); |
30 | | -} |
31 | | - |
32 | | -/// Uprobe attachment point: called on every allocation group exit (i.e. every Tokio task poll |
33 | | -/// that exits a component's group). bpftrace attaches here to clear the active component ID. |
34 | | -#[no_mangle] |
35 | | -#[inline(never)] |
36 | | -pub extern "C" fn vector_component_exit() { |
37 | | - std::hint::black_box(0u8); |
| 37 | +pub extern "C" fn vector_register_component( |
| 38 | + id: u8, |
| 39 | + name_ptr: *const u8, |
| 40 | + name_len: usize, |
| 41 | + labels_ptr: *const u8, |
| 42 | + labels_len: usize, |
| 43 | +) { |
| 44 | + std::hint::black_box((id, name_ptr, name_len, labels_ptr, labels_len)); |
38 | 45 | } |
0 commit comments