在DTrace
中,profile provider
是一种特殊的provider
,这个provider
提供的probe
起到一种类似定时器的作用。它可以根据用户设置的频率周期性地触发,这样用户就可以定期地采集感兴趣的数据,汇总以后作分析。
Profile provider
提供两种probe
:profile-n
和tick-n
。其中n
代表每秒probe
触发的频率,n
后面也可以带上时间后缀。举个例子:profile-100ns
(ns
表示纳秒),表示每100
纳秒触发一次。两种probe
的区别在于:每个CPU
都会触发执行profile-n
probe
,而只有一个CPU
会触发执行tick-n
probe
,所以使用profile-n
probe
时,需要考虑使用cpu-safe
的变量。让我们来做个试验,在Solaris
机器上,分别执行下面命令:“dtrace -n 'profile-1 {}
‘”和“dtrace -n 'tick-1 {}
‘”,输出如下:
bash-3.2# dtrace -n 'profile-1 {}'
dtrace: description 'profile-1 ' matched 1 probe
CPU ID FUNCTION:NAME
0 58553 :profile-1
1 58553 :profile-1
2 58553 :profile-1
3 58553 :profile-1
4 58553 :profile-1
5 58553 :profile-1
6 58553 :profile-1
7 58553 :profile-1
8 58553 :profile-1
9 58553 :profile-1
10 58553 :profile-1
11 58553 :profile-1
12 58553 :profile-1
13 58553 :profile-1
14 58553 :profile-1
15 58553 :profile-1
bash-3.2# dtrace -n 'tick-1 {}'
dtrace: description 'tick-1 ' matched 1 probe
CPU ID FUNCTION:NAME
9 53931 :tick-1
9 53931 :tick-1
9 53931 :tick-1
9 53931 :tick-1
从输出结果可以看到,profile-1
probe
在所有CPU
都执行了,而tick-1
probe
只在一个CPU
上执行了。
Profile probe
有两个输入参数:arg0
和arg1
。arg0
的值是probe
触发时,进程内核空间的指令计数器(program counter
)的值,如果当前进程运行在用户空间,则这个值是0
。与arg0
相反,arg1
的值是probe
触发时,进程用户空间的指令计数器(program counter
)的值,如果当前进程运行在内核空间,则这个值是0
。简单地讲,arg0
是0
,则arg1
一定不为0
,反之亦然。所以可以用输入参数来得知进程当前的运行状态,就像下面这个简单的例子:
profile-1ms
{
@ticks[arg0 ? "kernel" : "user"] = count();
}
最后以Brendan Gregg
的cpuwalk.d
脚本为例,来具体看一下如何使用profile probe
:
#pragma D option quiet
#pragma D option defaultargs
inline int MAXCPUID = 1024;
dtrace:::BEGIN
{
$1 ? printf("Sampling...\n") :
printf("Sampling... Hit Ctrl-C to end.\n");
seconds = 0;
}
profile:::profile-1000hz
/pid/
{
@sample[pid, execname] = lquantize(cpu, 0, MAXCPUID, 1);
}
profile:::tick-1sec
{
seconds++;
}
profile:::tick-1sec
/seconds == $1/
{
exit(0);
}
dtrace:::END
{
printa("\n PID: %-8d CMD: %s\n%@d", @sample);
}
这个脚本用来检查是否进程是否在多个CPU
上执行,运行脚本输出:
bash-3.2# ./cpuwalk.d
Sampling... Hit Ctrl-C to end.
^C
PID: 12476 CMD: mysqld
value ------------- Distribution ------------- count
0 | 0
1 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 4
2 | 0
PID: 24912 CMD: tail
value ------------- Distribution ------------- count
3 | 0
4 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1
5 | 0
PID: 19982 CMD: java
value ------------- Distribution ------------- count
4 | 0
5 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1
6 | 0
PID: 805 CMD: lsi_mrdsnmpagent
value ------------- Distribution ------------- count
1 | 0
2 |@@@@@@@@@@@@@@@@@@@@ 1
3 | 0
4 | 0
5 | 0
6 | 0
7 | 0
8 | 0
9 |@@@@@@@@@@@@@@@@@@@@ 1
10 | 0
PID: 3 CMD: fsflush
value ------------- Distribution ------------- count
0 | 0
1 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 12
2 | 0
PID: 6870 CMD: python
value ------------- Distribution ------------- count
11 | 0
12 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1
13 | 0
PID: 647 CMD: java
value ------------- Distribution ------------- count
13 | 0
14 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1
15 | 0
PID: 1683 CMD: python
value ------------- Distribution ------------- count
9 | 0
10 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 2
11 | 0
PID: 10156 CMD: java
value ------------- Distribution ------------- count
3 | 0
4 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 4
5 |@@@@@@@@ 1
6 | 0
PID: 11123 CMD: python
value ------------- Distribution ------------- count
10 | 0
11 |@@@@@@@@@@@@@@@@@@@@ 1
12 | 0
13 | 0
14 | 0
15 |@@@@@@@@@@@@@@@@@@@@ 1
16 | 0
PID: 24913 CMD: dtrace
value ------------- Distribution ------------- count
9 | 0
10 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 3
11 | 0
PID: 23874 CMD: java
value ------------- Distribution ------------- count
3 | 0
4 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 8
5 | 0
从执行结果可以看出,805
,10156
和11123
进程都在多个CPU
上执行。
参考资料:
(1)profile Provider;
(2)DTraceToolkit。