Skip to content

Commit 9f2399a

Browse files
committed
eBPF Debug Interrupt latency
1 parent b5ba3ff commit 9f2399a

File tree

11 files changed

+122
-69
lines changed

11 files changed

+122
-69
lines changed

agent/src/ebpf/Makefile

+7-6
Original file line numberDiff line numberDiff line change
@@ -134,12 +134,13 @@ endif
134134

135135
all: build
136136

137-
SOCKET_TRACE_ELFS := user/socket_trace_bpf_common.c \
138-
user/socket_trace_bpf_3_10_0.c \
139-
user/socket_trace_bpf_5_2_plus.c \
140-
user/socket_trace_bpf_kfunc.c \
141-
user/socket_trace_bpf_kylin.c \
142-
user/socket_trace_bpf_rt.c
137+
SOCKET_TRACE_ELFS :=
138+
#user/socket_trace_bpf_common.c \
139+
# user/socket_trace_bpf_3_10_0.c \
140+
# user/socket_trace_bpf_5_2_plus.c \
141+
# user/socket_trace_bpf_kfunc.c \
142+
# user/socket_trace_bpf_kylin.c \
143+
# user/socket_trace_bpf_rt.c
143144

144145
PERF_PROFILER_ELFS := user/perf_profiler_bpf_common.c
145146

agent/src/ebpf/kernel/include/perf_profiler.h

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ typedef enum {
3939
0: disable sampling; 1: enable sampling. */
4040
MINBLOCK_TIME_IDX, /* The minimum blocking time, applied in the profiler extension.*/
4141
RT_KERN, /* Indicates whether it is a real-time kernel.*/
42+
MAX_DELAY,
4243
PROFILER_CNT
4344
} profiler_idx;
4445

agent/src/ebpf/kernel/perf_profiler.bpf.c

+27-3
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,31 @@ MAP_STACK_TRACE(stack_map_b, STACK_MAP_ENTRIES)
6868
* switching between buffer a and buffer b.
6969
*/
7070
MAP_ARRAY(profiler_state_map, __u32, __u64, PROFILER_CNT)
71+
72+
MAP_PERARRAY(profiler_inter_map, __u32, __u64, 1)
73+
7174
PERF_EVENT_PROG(oncpu_profile) (struct bpf_perf_event_data *ctx)
7275
{
7376
__u32 count_idx;
7477

78+
count_idx = MAX_DELAY;
79+
__u64 *max_delay_ptr = profiler_state_map__lookup(&count_idx);
80+
if (max_delay_ptr == NULL)
81+
return 0;
82+
83+
count_idx = 0;
84+
__u64 *last_interrupt_time = profiler_inter_map__lookup(&count_idx);
85+
if (last_interrupt_time == NULL)
86+
return 0;
87+
88+
__u64 curr_time = bpf_ktime_get_ns()/1000000UL;
89+
__u64 diff = curr_time - *last_interrupt_time;
90+
*last_interrupt_time = curr_time;
91+
if (diff < *max_delay_ptr) {
92+
return 0;
93+
}
94+
95+
7596
count_idx = TRANSFER_CNT_IDX;
7697
__u64 *transfer_count_ptr = profiler_state_map__lookup(&count_idx);
7798

@@ -99,13 +120,15 @@ PERF_EVENT_PROG(oncpu_profile) (struct bpf_perf_event_data *ctx)
99120
if (transfer_count_ptr == NULL || sample_count_a_ptr == NULL ||
100121
sample_count_b_ptr == NULL || drop_count_ptr == NULL ||
101122
iter_count_ptr == NULL || error_count_ptr == NULL ||
102-
output_count_ptr == NULL || enable_ptr == NULL) {
123+
output_count_ptr == NULL || enable_ptr == NULL ||
124+
max_delay_ptr == NULL) {
103125
count_idx = ERROR_IDX;
104126
__u64 err_val = 1;
105127
profiler_state_map__update(&count_idx, &err_val);
106128
return 0;
107129
}
108130

131+
109132
if (unlikely(*enable_ptr == 0))
110133
return 0;
111134

@@ -117,12 +140,13 @@ PERF_EVENT_PROG(oncpu_profile) (struct bpf_perf_event_data *ctx)
117140
/*
118141
* CPU idle stacks will not be collected.
119142
*/
120-
if (key.tgid == key.pid && key.pid == 0)
121-
return 0;
143+
//if (key.tgid == key.pid && key.pid == 0)
144+
// return 0;
122145

123146
key.cpu = bpf_get_smp_processor_id();
124147
bpf_get_current_comm(&key.comm, sizeof(key.comm));
125148
key.timestamp = bpf_ktime_get_ns();
149+
key.duration_ns = diff;
126150

127151
/*
128152
* Note:

agent/src/ebpf/samples/rust/profiler/src/main.rs

+25-11
Original file line numberDiff line numberDiff line change
@@ -158,15 +158,29 @@ fn main() {
158158
env_logger::builder()
159159
.format_timestamp(Some(env_logger::TimestampPrecision::Millis))
160160
.init();
161+
let max_num = match std::env::args()
162+
.nth(1)
163+
.and_then(|arg| arg.parse::<i32>().ok())
164+
{
165+
Some(num) => num, // 保存 num 到变量 input_num
166+
None => {
167+
eprintln!("Usage: <program> <integer>");
168+
return; // 结束程序
169+
}
170+
};
171+
172+
// 在 main 中使用 input_num
173+
println!("Capture data where interrupt masking time is greater than or equal to a threshold of {}", max_num);
174+
161175

162176
// cat ./.profiler.folded |./flamegraph.pl --color=io --countname=ms > profiler-test.svg
163-
let log_file = CString::new("/var/log/deepflow-ebpf.log".as_bytes()).unwrap();
164-
let log_file_c = log_file.as_c_str();
177+
//let log_file = CString::new("/var/log/deepflow-ebpf.log".as_bytes()).unwrap();
178+
//let log_file_c = log_file.as_c_str();
165179
unsafe {
166180
// The first parameter passed by a null pointer can be
167181
// filled with std::ptr::null()
168-
if bpf_tracer_init(log_file_c.as_ptr(), true) != 0 {
169-
println!("bpf_tracer_init() file:{:?} error", log_file);
182+
if bpf_tracer_init(std::ptr::null(), true) != 0 {
183+
println!("bpf_tracer_init() file error");
170184
::std::process::exit(1);
171185
}
172186

@@ -186,27 +200,27 @@ fn main() {
186200

187201
// Used to test our DeepFlow products, written as 97 frequency, so that
188202
// it will not affect the sampling test of deepflow agent (using 99Hz).
189-
if start_continuous_profiler(97, 60, continuous_profiler_callback) != 0 {
203+
if start_continuous_profiler(19997, max_num, continuous_profiler_callback) != 0 {
190204
println!("start_continuous_profiler() error.");
191205
::std::process::exit(1);
192206
}
193207

194208
set_profiler_regex(
195-
CString::new("^(socket_tracer|java|deepflow-.*)$".as_bytes())
209+
CString::new("^(.*)$".as_bytes())
196210
.unwrap()
197211
.as_c_str()
198212
.as_ptr(),
199213
);
200214

201215
// CPUID will not be included in the aggregation of stack trace data.
202-
set_profiler_cpu_aggregation(0);
216+
set_profiler_cpu_aggregation(1);
203217

204218
bpf_tracer_finish();
205219

206-
//if cpdbg_set_config(60, debug_callback) != 0 {
207-
// println!("cpdbg_set_config() error");
208-
// ::std::process::exit(1);
209-
//}
220+
if cpdbg_set_config(600000, debug_callback) != 0 {
221+
println!("cpdbg_set_config() error");
222+
::std::process::exit(1);
223+
}
210224

211225
let stats = socket_tracer_stats();
212226
print!("{:#?}\n", stats);

agent/src/ebpf/user/probe.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -408,9 +408,9 @@ int program__attach_perf_event(int prog_fd, uint32_t ev_type,
408408
}
409409

410410
fds[i] = fd;
411-
ebpf_debug
412-
("attach perf event sample_freq %d pid %d cpu %d done\n",
413-
sample_freq, pid, i);
411+
ebpf_info
412+
("attach perf event sample_period %d sample_freq %d pid %d cpu %d done\n",
413+
sample_period, sample_freq, pid, i);
414414
}
415415

416416
memcpy((void *)attach_fds, (void *)fds, sizeof(fds));

agent/src/ebpf/user/proc.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,7 @@ void *get_symbol_cache(pid_t pid, bool new_cache)
796796
if (p->update_syms_table_time > 0
797797
&& curr_time >= p->update_syms_table_time) {
798798
if (p->is_java) {
799-
java_expired_update(h, &kv, p);
799+
//java_expired_update(h, &kv, p);
800800
symbolizer_proc_unlock(p);
801801
AO_DEC(&p->use);
802802
return (void *)p->syms_cache;

agent/src/ebpf/user/profile/perf_profiler.c

+25-13
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ static bool cpdbg_use_remote;
8686
static uint32_t cpdbg_start_time;
8787
static uint32_t cpdbg_timeout;
8888

89+
static int g_max_delay;
90+
8991
static u64 get_process_lost_count(struct profiler_context *ctx)
9092
{
9193
return atomic64_read(&ctx->process_lost_count);
@@ -167,6 +169,14 @@ static inline bool is_cpdbg_timeout(void)
167169
return false;
168170
}
169171

172+
void replace_semicolon_with_newline(char *str) {
173+
char *p = strchr(str, ';'); // 查找第一个 ';'
174+
while (p != NULL) {
175+
*p = '\n'; // 替换为 '\n'
176+
p = strchr(p + 1, ';'); // 查找下一个 ';'
177+
}
178+
}
179+
170180
static void print_cp_data(stack_trace_msg_t * msg)
171181
{
172182
char *timestamp = gen_timestamp_str(0);
@@ -180,15 +190,14 @@ static void print_cp_data(stack_trace_msg_t * msg)
180190
cid = (char *)msg->container_id;
181191

182192
char buff[DEBUG_BUFF_SIZE];
193+
replace_semicolon_with_newline(msg->data);
183194
snprintf(buff, sizeof(buff),
184-
"%s [cpdbg] type %d netns_id %lu container_id %s pid %u tid %u "
185-
"process_name %s comm %s stime %lu u_stack_id %u k_statck_id"
186-
" %u cpu %u count %u tiemstamp %lu datalen %u data %s\n",
187-
timestamp, msg->profiler_type, msg->netns_id,
188-
cid, msg->pid, msg->tid, msg->process_name, msg->comm,
189-
msg->stime, msg->u_stack_id,
190-
msg->k_stack_id, msg->cpu, msg->count,
191-
msg->time_stamp, msg->data_len, msg->data);
195+
"%s pid %u tid %u "
196+
"process_name %s comm %s "
197+
"cpu %u Interrupt_latency %lu ms\n\n%s\n",
198+
timestamp, msg->pid, msg->tid, msg->process_name, msg->comm,
199+
msg->cpu,
200+
msg->delay_ms, msg->data);
192201

193202
free(timestamp);
194203

@@ -350,6 +359,7 @@ static int create_profiler(struct bpf_tracer *tracer)
350359
ebpf_info(LOG_CP_TAG "=== oncpu profiler enabled ===\n");
351360
tracer->enable_sample = true;
352361
set_bpf_run_enabled(tracer, &oncpu_ctx, 0);
362+
set_bpf_max_delay(tracer, &oncpu_ctx, g_max_delay);
353363

354364
/*
355365
* create reader for read eBPF-profiler data.
@@ -689,6 +699,8 @@ int write_profiler_running_pid(void)
689699
int start_continuous_profiler(int freq, int java_syms_update_delay,
690700
tracer_callback_t callback)
691701
{
702+
g_max_delay = java_syms_update_delay;
703+
java_syms_update_delay = 60;
692704
char bpf_load_buffer_name[NAME_LEN];
693705
void *bpf_bin_buffer;
694706
uword buffer_sz;
@@ -698,8 +710,8 @@ int start_continuous_profiler(int freq, int java_syms_update_delay,
698710
* one profiler can be active due to the persistence required for Java symbol
699711
* generation, which is incompatible with multiple agents.
700712
*/
701-
if (check_profiler_is_running() != ETR_NOTEXIST)
702-
exit(EXIT_FAILURE);
713+
//if (check_profiler_is_running() != ETR_NOTEXIST)
714+
// exit(EXIT_FAILURE);
703715

704716
if (!run_conditions_check())
705717
exit(EXIT_FAILURE);
@@ -708,7 +720,7 @@ int start_continuous_profiler(int freq, int java_syms_update_delay,
708720
profiler_context_init(&oncpu_ctx, ONCPU_PROFILER_NAME, LOG_CP_TAG,
709721
PROFILER_TYPE_ONCPU, g_enable_oncpu,
710722
MAP_PROFILER_STATE_NAME, MAP_STACK_A_NAME,
711-
MAP_STACK_B_NAME, false, true,
723+
MAP_STACK_B_NAME, true, true,
712724
NANOSEC_PER_SEC / freq);
713725
g_ctx_array[PROFILER_CTX_ONCPU_IDX] = &oncpu_ctx;
714726

@@ -760,8 +772,8 @@ int start_continuous_profiler(int freq, int java_syms_update_delay,
760772

761773
tracer->state = TRACER_RUNNING;
762774

763-
if (write_profiler_running_pid() != ETR_OK)
764-
return (-1);
775+
//if (write_profiler_running_pid() != ETR_OK)
776+
// return (-1);
765777

766778
return (0);
767779
}

agent/src/ebpf/user/profile/perf_profiler.h

+1
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ typedef struct {
146146
u32 k_stack_id;
147147
u32 cpu;
148148
u32 count;
149+
u64 delay_ms;
149150
u8 comm[TASK_COMM_LEN];
150151
u8 process_name[TASK_COMM_LEN];
151152
u8 container_id[CONTAINER_ID_SIZE];

agent/src/ebpf/user/profile/profile_common.c

+29-31
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,26 @@ void set_bpf_run_enabled(struct bpf_tracer *t, struct profiler_context *ctx,
127127
enable_flag);
128128
}
129129

130+
void set_bpf_max_delay(struct bpf_tracer *t, struct profiler_context *ctx,
131+
u64 delay)
132+
{
133+
if (ctx->profiler_stop == 1)
134+
return;
135+
136+
if (bpf_table_set_value(t, ctx->state_map_name,
137+
MAX_DELAY, &delay) == false) {
138+
ebpf_warning("%sprofiler state map update error."
139+
"(%s max delay %lu) - %s\n",
140+
ctx->tag, ctx->state_map_name, delay,
141+
strerror(errno));
142+
return;
143+
}
144+
145+
ebpf_info("%s%s() success, interrupt check max delay:%dms\n", ctx->tag, __func__,
146+
delay);
147+
}
148+
149+
// set_bpf_max_delay(
130150
void set_bpf_rt_kern(struct bpf_tracer *t, struct profiler_context *ctx)
131151
{
132152
if (ctx->profiler_stop == 1)
@@ -638,6 +658,7 @@ static void set_stack_trace_msg(struct profiler_context *ctx,
638658
msg->pid = v->tgid;
639659
msg->tid = v->pid;
640660
msg->cpu = v->cpu;
661+
msg->delay_ms = v->duration_ns;
641662
msg->u_stack_id = (u32) v->userstack;
642663
msg->k_stack_id = (u32) v->kernstack;
643664
strcpy_s_inline(msg->comm, sizeof(msg->comm), v->comm, strlen(v->comm));
@@ -693,14 +714,14 @@ static void set_stack_trace_msg(struct profiler_context *ctx,
693714
msg->time_stamp = gettime(CLOCK_REALTIME, TIME_TYPE_NAN);
694715
if (ctx->use_delta_time) {
695716
// If sampling is used
696-
if (ctx->sample_period > 0) {
697-
msg->count = ctx->sample_period / 1000;
698-
} else {
717+
//if (ctx->sample_period > 0) {
718+
// msg->count = ctx->sample_period / 1000;
719+
//} else {
699720
// Using microseconds for storage.
700-
msg->count = v->duration_ns / 1000;
701-
}
721+
// msg->count = v->duration_ns / 1000;
722+
//}
702723
} else {
703-
msg->count = 1;
724+
//msg->count = 1;
704725
}
705726
msg->data_ptr = pointer_to_uword(&msg->data[0]);
706727

@@ -737,19 +758,6 @@ static inline void update_matched_process_in_total(struct profiler_context *ctx,
737758
(msg_hash, (stack_trace_msg_hash_kv *) & kv,
738759
(stack_trace_msg_hash_kv *) & kv) == 0) {
739760
__sync_fetch_and_add(&msg_hash->hit_hash_count, 1);
740-
if (ctx->use_delta_time) {
741-
if (ctx->sample_period > 0) {
742-
((stack_trace_msg_t *) kv.msg_ptr)->count +=
743-
(ctx->sample_period / 1000);
744-
} else {
745-
// Using microseconds for storage.
746-
((stack_trace_msg_t *) kv.msg_ptr)->count +=
747-
(v->duration_ns / 1000);
748-
}
749-
750-
} else {
751-
((stack_trace_msg_t *) kv.msg_ptr)->count++;
752-
}
753761
return;
754762
}
755763

@@ -807,8 +815,8 @@ static void aggregate_stack_traces(struct profiler_context *ctx,
807815
* that it is an invalid value, the CPUID will not be included in
808816
* the aggregation.
809817
*/
810-
if (ctx->cpu_aggregation_flag == 0)
811-
v->cpu = CPU_INVALID;
818+
//if (ctx->cpu_aggregation_flag == 0)
819+
// v->cpu = CPU_INVALID;
812820

813821
/*
814822
* Uniform idle process names to reduce the aggregated count of stack
@@ -940,16 +948,6 @@ static void aggregate_stack_traces(struct profiler_context *ctx,
940948
(stack_trace_msg_hash_kv *) & kv) == 0) {
941949
__sync_fetch_and_add(&msg_hash->hit_hash_count, 1);
942950
if (ctx->use_delta_time) {
943-
if (ctx->sample_period > 0) {
944-
((stack_trace_msg_t *) kv.msg_ptr)->
945-
count +=
946-
(ctx->sample_period / 1000);
947-
} else {
948-
// Using microseconds for storage.
949-
((stack_trace_msg_t *) kv.msg_ptr)->
950-
count += (v->duration_ns / 1000);
951-
}
952-
953951
} else {
954952
((stack_trace_msg_t *) kv.msg_ptr)->count++;
955953
}

agent/src/ebpf/user/profile/profile_common.h

+2
Original file line numberDiff line numberDiff line change
@@ -181,4 +181,6 @@ bool check_profiler_regex(struct profiler_context *ctx, const char *name);
181181
// Check if the profiler is currently running.
182182
bool profiler_is_running(void);
183183
void set_bpf_rt_kern(struct bpf_tracer *t, struct profiler_context *ctx);
184+
void set_bpf_max_delay(struct bpf_tracer *t, struct profiler_context *ctx,
185+
u64 delay);
184186
#endif /*DF_USER_PROFILE_COMMON_H */

0 commit comments

Comments
 (0)