cpu相关probe
cpu()--返回当前CPU number
scheduler.cpu_off--进程在cpu上停止执行时调用;task_prev即将离开的进程;task_next即将执行的进程;name--probe point;idle--当前进程是否idle
scheduler.cpu_on--进程在cpu上开始执行时调用;task_prev上一个运行的进程;name--probe point;idle当前进程是否idle
scheduler.balance--CPU尝试寻找更多的任务;name--probe point名字
scheduler.ctxswitch--进程切换时调用;prev_id被切换出去的pid;next_id被切换进的pid;prev_task_name/next_task_name;
scheduler.migrate--在cpu间迁移的task;cpu_from源cpu;cpu_to目标cpu;task进程名;pid进程id;priority进程优先级;
scheduler.process_fork--衍生进程;parent_pid/child_pid
scheduler.wakeup--被唤醒的进程;task_cpu/task_pid/task_priority/task_state
irq_handler.entry/exit--调用/退出中断时触发;dev_name设备名;flags--IRQ handler的flags;irq中断号;dir指向proc/irq/NN/name;handler中断处理函数
softirq.entry/exit--调用/退出软中断;vec软中断容器;h;vec_nr软中断容器号;action软中断控制器指针
例1
当系统sys或者cs较高时,可以侦测哪些由哪些进程引起
每秒打印出占用cpu和进程切换最多的5个任务
#! /usr/bin/env stap
probe scheduler.cpu_on {
sys_cpu[execname()]++
}
probe scheduler.cpu_off {
cs_cpu[task_prev,task_next]++
}
probe timer.s(1) {
foreach (taskname in sys_cpu- limit 5) {
printf(" %s execute %d times on cpu %d ",taskname,sys_cpu[task_prev])
)
foreach ([prename,nextname] in cs_cpu- limit 5) {
printf(" s%[d%] --> s%[d%], total count d% ", task_execname(task_prev),task_pid(task_prev),task_execname(task_next),task_pid(task_next),cs_cpu[task_prev,task_next])
}
}
例2
--smp_call_function
当进程申请跨CPU中断时需要调用此函数,相当消耗较高
# stap scf.stp -c "sleep 0.2"
#! /usr/bin/env stap
global traces
probe begin { printf(" starting, press ctrl + c to stop\n") }
probe kernel.function("smp_call_function") {
traces[pid(), pexecname(), backtrace()] ++
}
probe end {
foreach ([pid, name, stack] in traces-) { --按出现频率排序
printf("trace[%d,%s,\n",pid,name)
printf_syms(stack)
printf("] =%d\n", traces[pid,name,stack])
}
}
process/chng_cpu.stp
以任务名作为输入参数,当其切换cpu时记录当前CPU和线程id,以及被触发的内核函数
#stap chng_cpu.stp -c "sleep 0.2" bash
#! /usr/bin/env stap
global threads
probe scheduler.cpu_on{
if(threads[pid()] != cpu() && execname == @1) {
printf("\nthread %d (%s) context switched on cpu%d state: %d\n", tid(),execname(),cpu(),task_state(task_current()));
print_sysm(backtrace());
thread[pid] = cpu();
}
}
--print_sysm用于打印内核栈
process/migrate.stp
跟踪在CPU间迁移的任务,输入参数为进程名
#! /usr/bin/env stap
probe kernel.function("_migrate_task") {
comm = kernel_string($p->comm);
if (comm == @1) {
printf("thread %d(%s) is migrating from %d to %d\n", pid(),comm,$src_cpu,$dest_cpu);
}
}
interrupt/interrupts-by-dev.stp
每秒查获发起中断的设备并按频率排序
# stap interrupts-by-dev.stp -c "sleep 0.2"
#! /usr/bin/env stap
global devices
probe irq_handler.entry {
devices[dev_name]++;
}
probe timer.ms(100) {
foreach (devname in devices-) {
printf(" %20s : %5d \n", kernel_string(devname),devices[dev_name]);
}
}
很帅的一个案例
http://blog.yufeng.info/archives/2037
背景:
Mysql服务器使用俩千兆网卡绑定做LB,数据库流量可达150M;
压力测试发现一个cpu core很繁忙,通过mpstat显示soft%占用率很高;
以下是解决思路:
OS为RH 6.1
查看现有网卡设置,调用lspci查看PCI总线信息
查看 /proc/net/bonding/bond0,两个网卡绑定方式为active – backup
查看中断/软中断信息 /proc/interrupts 和/proc/softirqs
粗略浏览可以验证各个CPU core的NET_TX/NET_RX不是太均衡
编写简单的stap脚本并调用stap再次检测
获知硬解析是均衡的 是软解析的问题, 同时用到addr2line命令
其余命令
lscpu –多核CPU查看core的对应关系
Dmesg
Service irqbalance stop
解决方案:
采用多队列万M网卡 / 采用google 的RPS patch分散软中断
采用简易脚本—事后确认由于有硬件中断平衡,不需要该脚本,而是采用另外一个
$cat em.sh
#! /bin/bash
for i in `seq 0 7`
do
echo f|sudo tee /sys/class/net/em1/queues/rx-$i/rps_cpus >/dev/null
echo f|sudo tee /sys/class/net/em2/queues/rx-$i/rps_cpus >/dev/null
done
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/15480802/viewspace-762746/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/15480802/viewspace-762746/