Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libbpf-tools/offcputime: Add multi process/thread support #5111

Merged
merged 2 commits into from
Oct 20, 2024

Conversation

ekyooo
Copy link
Contributor

@ekyooo ekyooo commented Sep 20, 2024

This is a test example.

  # ./offcputime -p 16,48
    Tracing off-CPU time (us) of PID [16, 48]... Hit Ctrl-C to end.
        bpf_prog_a42aae11c0bc18f2_sched_switch
        bpf_prog_a42aae11c0bc18f2_sched_switch
        bpf_trace_run4
        __traceiter_sched_switch
        __schedule
        schedule
        worker_thread
        kthread
        ret_from_fork
        ret_from_fork_asm
        -                kworker/2:1 (48)
            3353019

        bpf_prog_a42aae11c0bc18f2_sched_switch
        bpf_prog_a42aae11c0bc18f2_sched_switch
        bpf_trace_run4
        __traceiter_sched_switch
        __schedule
        schedule
        rcu_gp_kthread
        kthread
        ret_from_fork
        ret_from_fork_asm
        -                rcu_preempt (16)
            1720974

@Bojun-Seo
Copy link
Contributor

I think help message should be changed together.
For example, Trace this PID only doesn't explain the -p option any more after this patch merged.

@ekyooo
Copy link
Contributor Author

ekyooo commented Sep 27, 2024

I think help message should be changed together. For example, Trace this PID only doesn't explain the -p option any more after this patch merged.

Thank you for the review. It's fixed.

printf(" TID [");
for (i = 0; i < MAX_TID_NR && env.tids[i]; i++)
printf("%d%s", env.tids[i], (i < MAX_TID_NR - 1 && env.tids[i + 1]) ? ", " : "]");
} else {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we print both PID and TID in the above?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's modified. thank you.

if (env.pids[0])
obj->rodata->filter_by_tgid = true;
else if (env.tids[0])
obj->rodata->filter_by_pid = true;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we do both obj->rodata->filter_by_tgid and obj->rodata->filter_by_pid?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's modified. thank you.

}
}
}
else if (env.tids[0]) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove above 'else'?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean to support the use of the -p option and the -t option simultaneously?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original code does seem to support both pid and tgid though.

static bool allow_record(struct task_struct *t)
{       
        if (targ_tgid != -1 && targ_tgid != t->tgid)
                return false;
        if (targ_pid != -1 && targ_pid != t->pid)
                return false;
        if (user_threads_only && t->flags & PF_KTHREAD)
                return false;
        else if (kernel_threads_only && !(t->flags & PF_KTHREAD))
                return false;
        if (state != -1 && get_task_state(t) != state)
                return false;
        return true;
}

It is totally possible that user provides both tgid and pid where 'pid' is one of tasks under tgid. But in that case, the tracing is actually for 'pid'. So we can consider the tracing for 'pid' then.

So in the above, I guess we might want to do both. Please double check though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your detailed feedback.
I understood that you meant to output the OR result of the -p and -t options.

  1. To clarify, the original code does not support the simultaneous use of both options. The allow_record function is a filtering function, so only threads that satisfy both tgid and pid conditions are recorded. When using -p and -t simultaneously, threads that satisfy only one of the two conditions are filtered out.
    For your information, this is the result of testing the simultaneous use of -p and -t without these patch sets.
// use -p option only
# ./offcputime -p 26209
Tracing off-CPU time (us)... Hit Ctrl-C to end.
^C    bpf_prog_efc0a21eee79af12_sched_switch
    bpf_prog_efc0a21eee79af12_sched_switch
    bpf_trace_run4
    __traceiter_sched_switch
    __schedule
    schedule
    irqentry_exit_to_user_mode
    asm_sysvec_apic_timer_interrupt
    strlen
    b
    a
    main
    __libc_start_main
    -                test-strlen-abc (26209)
        78

// use -t option only
# ./offcputime -t 16
Tracing off-CPU time (us)... Hit Ctrl-C to end.
^C    bpf_prog_efc0a21eee79af12_sched_switch
    bpf_prog_efc0a21eee79af12_sched_switch
    bpf_trace_run4
    __traceiter_sched_switch
    __schedule
    schedule
    schedule_timeout
    rcu_gp_fqs_loop
    rcu_gp_kthread
    kthread
    ret_from_fork
    ret_from_fork_asm
    -                rcu_preempt (16)
        4005

// use -p and -t option together
# ./offcputime -p 26209 -t 16
Tracing off-CPU time (us)... Hit Ctrl-C to end.
#

This behavior is the same in offcputime.py, profile.py, and profile.c.

  1. However, I agree with your opinion that we should support the simultaneous use of both options because it is more reasonable and accurate. The reason I checked your intention was to ensure the change, as it could also affect offcputime.py, profile.py, and profile.c.

Now, I have updated the patches to support the simultaneous use of both options.
Thank you for your good opinion, and please provide feedback if there is any miscommunication.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, you meant to output the AND result of the -p and -t options?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original code supports both PID and TGID using an AND condition, as you mentioned. Therefore, I have modified this patch to focus solely on multi-process/thread support without altering the AND rule.

However, as far as I know, many other tools like perf and SystemTap use an OR condition in these cases. It would be beneficial to discuss the rule for usability and consistency across tools.

Thank you.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After this PR is completed, I'm going to create another PR to discuss with you the output of the OR result for the -p and -t options. Thank you.

int str_to_int(const char *src, void *dest)
{
*(int*)dest = strtol(src, NULL, 10);
return errno;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since str_to_int() and str_to_long() are in trace_helpers.c, we should add 'error = 0;' before strtol(). It is possible that errno is not 0 before strtol() and if strtol() works perfectly, errno won't change and the return value will be non-zero.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's right. It's fixed. Thank you very much.

@ekyooo ekyooo force-pushed the offcpu_multi branch 2 times, most recently from a166f61 to 30d4c8c Compare October 9, 2024 05:58
This is a test example.

  # ./offcputime -p 16,48
    Tracing off-CPU time (us) of PID [16, 48]... Hit Ctrl-C to end.
        bpf_prog_a42aae11c0bc18f2_sched_switch
        bpf_prog_a42aae11c0bc18f2_sched_switch
        bpf_trace_run4
        __traceiter_sched_switch
        __schedule
        schedule
        worker_thread
        kthread
        ret_from_fork
        ret_from_fork_asm
        -                kworker/2:1 (48)
            3353019

        bpf_prog_a42aae11c0bc18f2_sched_switch
        bpf_prog_a42aae11c0bc18f2_sched_switch
        bpf_trace_run4
        __traceiter_sched_switch
        __schedule
        schedule
        rcu_gp_kthread
        kthread
        ret_from_fork
        ret_from_fork_asm
        -                rcu_preempt (16)
            1720974
Add a utility API to split and convert strings for argument parsing.

Also, apply the API usage to offcputime and profile to remove duplicates.
@yonghong-song yonghong-song merged commit 86d006a into iovisor:master Oct 20, 2024
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants