gettimeofday函数_内核态调测工具:ftrace(六)-ftrace应用:跟踪&统计函数耗时

本文通过一个实例分析了在CPU压力大时,使用ftrace工具跟踪并统计gettimeofday函数执行耗时的问题。通过ftrace在test.c中添加跟踪代码,发现CPU1长时间运行其他任务导致test_trace执行延迟,揭示了CFS调度策略在高负载下的现象,并建议尝试将任务设置为SCHED_RR以改善执行及时性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题

实际应用中,当系统CPU压力较大,某些固定频率触发的任务突然不稳定起来,或者出现(比较关注性能的)某函数的执行耗时出现波动,这种情况是为什么呢?是函数本身不稳定,还是系统导致?

举例test.c:

#include <stdio.h>
#include <sys/time.h>

int delaytime(int t) {
        int i, j;
        for (i = 0; i < t; i++)
                for (j = 0; j < 5000; j++);
}

void main() {
        struct timeval tv1, tv2;

        gettimeofday(&tv1, NULL);
        delaytime(100);
        gettimeofday(&tv2, NULL);

        printf("diff: %ldusn", 1000000 * (tv2.tv_sec - tv1.tv_sec) + (tv2.tv_usec - tv1.tv_usec));
}

如下执行:

$ stress -c 8 &
$ taskset -c 6 ./test
diff: 1045us
$ taskset -c 6 ./test
diff: 1124us
$ taskset -c 6 ./test
diff: 1444us
$ taskset -c 6 ./test
diff: 2162us
$ taskset -c 6 ./test
diff: 11995us
$ taskset -c 6 ./test
diff: 1067us

如上,一个固定的for循环在CPU加压的情况下,执行耗时不再稳定。

Ftrace跟踪

利用之前讲到的知识

Hello小崔:内核态调测工具:ftrace(三)-ftrace在C程序中应用​zhuanlan.zhihu.com
zhihu-card-default.svg

在test.c中添加跟踪代码:

$ cat test_trace.c
#include <stdio.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int delaytime(int t) {
        int i, j;
        for (i = 0; i < t; i++)
                for (j = 0; j < 5000; j++);
}

void main() {
        struct timeval tv1, tv2;
        int fd_sched = open("/sys/kernel/debug/tracing/events/sched/enable", O_CREAT | O_RDWR, 0666);
        int fd_irq = open("/sys/kernel/debug/tracing/events/irq/enable", O_CREAT | O_RDWR, 0666);
        int fd_mark = open("/sys/kernel/debug/tracing/trace_marker", O_CREAT | O_RDWR, 0666);
        int fd_trace = open("/sys/kernel/debug/tracing/tracing_on", O_CREAT | O_RDWR, 0666);

        write(fd_trace, "1", 2); // enable ftrace
        write(fd_sched, "1", 2); // enable sched event
        write(fd_irq, "1", 2); // enable irq event

        while (1) {
                gettimeofday(&tv1, NULL);
                write(fd_mark, "start delay", 12); // add mark
                delaytime(100);
                write(fd_mark, "end delay", 12); // end mark
                gettimeofday(&tv2, NULL);

                if ((1000000 * (tv2.tv_sec - tv1.tv_sec) + (tv2.tv_usec - tv1.tv_usec)) > 10000) {
                        printf("break!n");
                        write(fd_trace, "1", 2); // find something wrong, stop ftrace
                        write(fd_sched, "0", 2);
                        write(fd_irq, "0", 2);
                        break;
                }
        }
        close(fd_mark);
        close(fd_trace);
        close(fd_sched);
        close(fd_irq);
}

重新执行:

$ stress -c 8 &
$ taskset -c 6 ./test_trace
break!
$ killall stress
$ sudo cat /sys/kernel/debug/tracing/trace > trace.log
$ vim trace.log

找到最终出现时间过长是在CPU1:

d6c106908cb69dd3e440801fb119b625.png
cat trace.log |grep 001
test_trace-6345  [001] .... 8271351.623351: tracing_mark_write: start delay             vim-27246 [000] d.h. 8271351.623846: sched_waking: comm=containerd pid=3658 prio=120 target_cpu=000
          stress-6314  [002] d.h. 8271351.624001: softirq_raise: vec=1 [action=TIMER]
          stress-6317  [004] d.h. 8271351.624001: softirq_raise: vec=1 [action=TIMER]
      test_trace-6345  [001] d.h. 8271351.624002: softirq_raise: vec=1 [action=TIMER]
      test_trace-6345  [001] d.h. 8271351.624003: softirq_raise: vec=9 [action=RCU]
      test_trace-6345  [001] d.h. 8271351.624003: sched_stat_runtime: comm=test_trace pid=6345 runtime=3999453 [ns] vruntime=3795265129978053 [ns]
      test_trace-6345  [001] .Ns. 8271351.624006: softirq_entry: vec=1 [action=TIMER]
      test_trace-6345  [001] .Ns. 8271351.624007: softirq_exit: vec=1 [action=TIMER]
      test_trace-6345  [001] .Ns. 8271351.624007: softirq_entry: vec=9 [action=RCU]
      test_trace-6345  [001] .Ns. 8271351.624008: softirq_exit: vec=9 [action=RCU]
      test_trace-6345  [001] dN.. 8271351.624009: sched_stat_runtime: comm=test_trace pid=6345 runtime=5493 [ns] vruntime=3795265129983546 [ns]
      test_trace-6345  [001] d... 8271351.624010: sched_switch: prev_comm=test_trace prev_pid=6345 prev_prio=120 prev_state=R ==> next_comm=stress next_pid=6312 next_prio=120
          stress-6317  [004] d.h. 8271351.628001: softirq_raise: vec=9 [action=RCU]
          stress-6317  [004] d.h. 8271351.628001: sched_stat_runtime: comm=stress pid=6317 runtime=3999078 [ns] vruntime=2602931922779310 [ns]
          stress-6316  [003] d.h. 8271351.628001: softirq_raise: vec=1 [action=TIMER]
          stress-6314  [002] d.h. 8271351.628001: sched_stat_runtime: comm=stress pid=6314 runtime=3999141 [ns] vruntime=2856602266991255 [ns]
          stress-6316  [003] d.h. 8271351.628001: softirq_raise: vec=9 [action=RCU]
          stress-6312  [001] d.h. 8271351.628002: softirq_raise: vec=1 [action=TIMER]
          stress-6312  [001] d.h. 8271351.628002: sched_stat_runtime: comm=stress pid=6312 runtime=3993578 [ns] vruntime=3795265118124082 [ns]
          stress-6312  [001] ..s. 8271351.628005: softirq_entry: vec=1 [action=TIMER]
          stress-6312  [001] ..s. 8271351.628005: softirq_exit: vec=1 [action=TIMER]
          stress-6317  [004] d.h. 8271351.632001: softirq_raise: vec=9 [action=RCU]
          stress-6314  [002] d.h. 8271351.632001: softirq_raise: vec=1 [action=TIMER]
          stress-6315  [005] d.h. 8271351.632001: softirq_raise: vec=9 [action=RCU]
          stress-6317  [004] d.h. 8271351.632001: sched_stat_runtime: comm=stress pid=6317 runtime=3999776 [ns] vruntime=2602931926779086 [ns]
          stress-6314  [002] d.h. 8271351.632001: softirq_raise: vec=9 [action=RCU]
          stress-6315  [005] d.h. 8271351.632001: sched_stat_runtime: comm=stress pid=6315 runtime=3997437 [ns] vruntime=773930908522608 [ns]
          stress-6314  [002] d.h. 8271351.632001: sched_stat_runtime: comm=stress pid=6314 runtime=3999959 [ns] vruntime=2856602270991214 [ns]
          stress-6312  [001] d.h. 8271351.632001: softirq_raise: vec=1 [action=TIMER]
          stress-6316  [003] d.h. 8271351.632001: softirq_raise: vec=1 [action=TIMER]
          stress-6312  [001] d.h. 8271351.632002: softirq_raise: vec=9 [action=RCU]
          stress-6312  [001] d.h. 8271351.632002: sched_stat_runtime: comm=stress pid=6312 runtime=3999764 [ns] vruntime=3795265122123846 [ns]
          stress-6312  [001] ..s. 8271351.632004: softirq_entry: vec=1 [action=TIMER]
          stress-6312  [001] ..s. 8271351.632004: softirq_exit: vec=1 [action=TIMER]
          stress-6312  [001] ..s. 8271351.632005: softirq_entry: vec=9 [action=RCU]
          stress-6312  [001] ..s. 8271351.632022: softirq_exit: vec=9 [action=RCU]
          stress-6316  [003] dN.. 8271351.632896: sched_stat_runtime: comm=stress pid=6316 runtime=882192 [ns] vruntime=1181827362000120 [ns]
          stress-6317  [004] d.h. 8271351.636001: softirq_raise: vec=9 [action=RCU]
          stress-6317  [004] d.h. 8271351.636001: sched_stat_runtime: comm=stress pid=6317 runtime=4000319 [ns] vruntime=2602931930779405 [ns]
          stress-6315  [005] d.h. 8271351.636002: sched_stat_runtime: comm=stress pid=6315 runtime=4001146 [ns] vruntime=773930912523754 [ns]
          stress-6312  [001] d.h. 8271351.636003: softirq_raise: vec=1 [action=TIMER]
          stress-6312  [001] d.h. 8271351.636003: softirq_raise: vec=9 [action=RCU]
          stress-6312  [001] d.h. 8271351.636004: sched_stat_runtime: comm=stress pid=6312 runtime=4001619 [ns] vruntime=3795265126125465 [ns]
          stress-6318  [007] d.h. 8271351.636004: sched_stat_runtime: comm=stress pid=6318 runtime=4001016 [ns] vruntime=1587598060233969 [ns]
             vim-27246 [000] d.h. 8271351.636005: sched_stat_runtime: comm=vim pid=27246 runtime=4000114 [ns] vruntime=365313085464828 [ns]
          stress-6312  [001] ..s. 8271351.636007: softirq_entry: vec=1 [action=TIMER]
          stress-6312  [001] ..s. 8271351.636008: softirq_exit: vec=1 [action=TIMER]
          stress-6312  [001] ..s. 8271351.636008: softirq_entry: vec=9 [action=RCU]
          stress-6312  [001] ..s. 8271351.636008: softirq_exit: vec=9 [action=RCU]
          stress-6312  [001] d.h. 8271351.640003: softirq_raise: vec=1 [action=TIMER]
          stress-6312  [001] d.h. 8271351.640004: softirq_raise: vec=9 [action=RCU]
          stress-6312  [001] d.h. 8271351.640004: sched_stat_runtime: comm=stress pid=6312 runtime=4000085 [ns] vruntime=3795265130125550 [ns]
          stress-6312  [001] .Ns. 8271351.640007: softirq_entry: vec=1 [action=TIMER]
          stress-6312  [001] .Ns. 8271351.640008: softirq_exit: vec=1 [action=TIMER]
          stress-6312  [001] .Ns. 8271351.640008: softirq_entry: vec=9 [action=RCU]
          stress-6312  [001] .Ns. 8271351.640008: softirq_exit: vec=9 [action=RCU]
          stress-6312  [001] dN.. 8271351.640009: sched_stat_runtime: comm=stress pid=6312 runtime=5234 [ns] vruntime=3795265130130784 [ns]
          stress-6313  [006] ..s. 8271351.640010: softirq_exit: vec=1 [action=TIMER]
          stress-6313  [006] ..s. 8271351.640010: softirq_entry: vec=9 [action=RCU]
             vim-27246 [000] ..s. 8271351.640010: softirq_entry: vec=1 [action=TIMER]
             vim-19564 [002] ..s. 8271351.640010: softirq_entry: vec=1 [action=TIMER]
          stress-6313  [006] ..s. 8271351.640010: softirq_exit: vec=9 [action=RCU]
             vim-27246 [000] ..s. 8271351.640010: softirq_exit: vec=1 [action=TIMER]
             vim-27246 [000] ..s. 8271351.640011: softirq_entry: vec=7 [action=SCHED]
             vim-19564 [002] ..s. 8271351.640011: softirq_exit: vec=1 [action=TIMER]
          stress-6312  [001] d... 8271351.640011: sched_switch: prev_comm=stress prev_pid=6312 prev_prio=120 prev_state=R ==> next_comm=test_trace next_pid=6345 next_prio=120
             vim-19564 [002] ..s. 8271351.640011: softirq_entry: vec=9 [action=RCU]
             vim-19564 [002] ..s. 8271351.640011: softirq_exit: vec=9 [action=RCU]
      test_trace-6345  [001] .... 8271351.640410: tracing_mark_write: end delay      test_trace-6345  [001] d... 8271351.640489: sched_waking: comm=kworker/u16:0 pid=20387 prio=120 target_cpu=000

结论

最终跟踪到当时CPU1长时间在运行stress,在8271351.640011时间才切回test_trace运行。

现在知道为什么在CPU压力大的情况下,有时候任务不能及时执行的原因了吧,这是CFS调度策略的现象。

试着将任务设置成SCHED_RR看下是否可以保证运行。

$ sudo chrt -r 99 ./test
diff: 1051us
$ sudo chrt -r 99 ./test
diff: 1068us
$ sudo chrt -r 99 ./test
diff: 1024us
$ sudo chrt -r 99 ./test
diff: 1072us
$ sudo chrt -r 99 ./test
diff: 1039us
$ sudo chrt -r 99 ./test
diff: 1019us
$ sudo chrt -r 99 ./test
diff: 1041us
$ sudo chrt -r 99 ./test
diff: 1036us
$ sudo chrt -r 99 ./test
diff: 1047us
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值