arthur-zhang / morning-up-up

78 stars 6 forks source link

1208 分享:off cpu 火焰图 #31

Open arthur-zhang opened 3 years ago

arthur-zhang commented 3 years ago

作业: 生成一个 off cpu 火焰图

IKNOWLJT commented 3 years ago

3. 绘制在off-cpu的火焰图

3.1 测试代码:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *fun_test(void *args) {
    while(1){
        pthread_mutex_lock(&mutex);
        usleep(3);
        pthread_mutex_unlock(&mutex);
        int a = 0;
        for(a = 0; a < 10000 ; a = a + 1 ){
            printf("hello world\n");
        }
    }
}
int main() {
    int num = 100;
    pthread_t threads[num];
    int i;
    for (i = 0; i < num; ++i) {
        pthread_create(&threads[i], NULL, fun_test, NULL);
    }
    for (i = 0; i < num; ++i) {
        pthread_join(threads[i], NULL);
    }
    return 0;
}
3.2 代码分析:
从上面代码中我们可以分析到,从mian函数中我们创建了100个线程去执行fun_test 方法
1. fun_test中会调用所有的线程都回去竞争全局锁 mutex 拿到的线程再去执行 usleep 3微妙,
2. 拿到锁的线程然后打印1000次的hello world

在上述的两个过程中是存在会出现off-cpu的地方
1. 一个发生在因为usleep 导致竞争锁的时候 
2. 一个发生在打印的时候,打印的时候会进行sys_write系统调用后,sys_write中有一个tty_write的n_tty_write等待一个mutex的代码上面。
3.3 采集数据

sudo ./sample-bt-off-cpu -p 'pidof a.out' -t 2 -u > tmp.bt

3.4 折叠堆栈数据,绘制火焰图

./stackcollapse-stap.pl tmp.bt > flame.cbt

./flamegraph.pl flame.cbt > flame.svg

image-20201208201125649

3.5 sample-bt-off-cpu 采集off-cpu数据的原理

image-20201208201305212

可以看到sample-bt-off-cpu 是监听了获取到CPU和失去CPU的两个事件,通过这两个事件之前的时间差值计算出,堆栈在0ff-cpu上的时间,然后通过时间计算出堆栈在off-cpu的比例,与获取on-cpu不同的是,on-cpu是根据定时器很高频率的对还在运行中的堆栈做计数计算的,但是off-cpu是监听的在cpu获取和失去的时间差值统计的。

4. 系统调用

计算机系统的各种硬件资源是有限的,在现代多任务操作系统上同时运行的多个进程都需要访问这些资源,为了更好的管理这些资源进程是不允许直接操作的,所有对这些资源的访问都必须有操作系统控制。也就是说操作系统是使用这些资源的唯一入口,而这个入口就是操作系统提供的系统调用(System Call),系统调用和普通库函数调用非常相似,只是系统调用由操作系统核心提供,运行于内核态,而普通的函数调用由函数库或用户自己提供,运行于用户态

在linux中系统调用是用户空间访问内核的唯一手段,除异常和陷入外,他们是内核唯一的合法入口。操作系统一般是通过中断从用户态切换到内核态。中断就是一个硬件或软件请求,要求CPU暂停当前的工作,去处理更重要的事情。

系统调用在用户空间进程和硬件设备之间添加了一个中间层。该层主要作用有三个:

4.1 查看系统调用

strace 在linux系统中某个程序执行时进行的系统调用可以通过strace命令来查看,多线程的线程必须加上 -f 参数