计算特定工作负载的上下文切换次数的 3 种不同方法提供了 2 种不同的答案

计算特定工作负载的上下文切换次数的 3 种不同方法提供了 2 种不同的答案

我在 Google 云机器上有一个 Centos7 系统,运行一个多线程数据库服务器,该服务器在 70 秒内(正负 1 秒)执行一组特定的查询。我想知道服务器在运行此工作负载时进行了多少次上下文切换。

服务器 pid 是 11850。

我使用了 3 种不同的计数方法:

方法一:

开始

perf -e context-switches -p 11850

在一个窗口中,然后立即在另一个窗口中运行数据库客户端。然后在客户端完成后立即终止 perf。

输出结果为

 Performance counter stats for process id '11850':

     5,831,206      context-switches          #    0.004 M/sec

    70.607962486 seconds time elapsed

方法 2

开始

pidstat -tw -p 11850 70 1 >pidstat.out

在一个窗口中并立即在另一个窗口中运行客户端。

pidstat 和客户端将在一秒钟内完成。当这种情况发生时,将 pidstat.out 中的所有 cswch/s 和 nvcswch/s 值相加,并将结果乘以 70。

这给出与方法 1 几乎相同的结果。

方法 3

在一个窗口中运行包含以下命令的脚本

vmstat -s|grep "CPU context switches" 
sleep 70
vmstat -s|grep "CPU context switches" 

然后立即在另一个窗口中运行客户端。客户端和第二个 vmstat 将在一秒钟内完成。

vmstat 输出如下

    439394923 CPU context switches
    450457926 CPU context switches

用第二个数字减去第一个数字得出的结果为 11,063,003,几乎是其他两种方法结果的两倍。

由于系统上没有运行其他任何程序,并且空闲系统上的上下文切换的正常速率约为 100/秒,因此 vmstat 方法似乎对上下文切换进行了双重计算。

这是一个错误,还是我遗漏了什么?

答案1

需要检查的是,只有被检查的 PID 才能进行上下文切换这一假设。

检查所有 CPU 上的上下文切换,例如perf top -e context-switches -a。您可能会看到其他任务(包括其他数据库线程和内核任务)在 CPU 上跳转和退出。

比上下文切换计数器更有用每周期指令数等统计数据。获得那些perf stat。好的 IPC 大于 1。当然,对于 CPU 受限的工作负载。缓慢的存储意味着 CPU 永远等待。

答案2

如果你想获取进程内的上下文切换次数,你可以查看GetRUsage 系统调用

例如,在 Golang 中:

    var usage syscall.Rusage
    if err := syscall.Getrusage(syscall.RUSAGE_SELF, &usage); err != nil {
        fmt.Printf("Error: unable to gather resource usage data: %v\n", err)
    }

相关内容