这次我们修改模拟服务器守护进程的mydtrace.c源码,给原有的函数增加一些参数,算法上做一些字符串拼接和加法操作并打印出参数和返回值,然后利用sleep模拟系统瓶颈,a_1函数sleep(2)停顿2秒,b_1函数sleep(3)停顿3秒,最后我们编写跟踪探测脚本mydtrace.sh收集系统运行数据,分析瓶颈所在。
1. 修改mydtrace.c源码,增加参数,增加字符串拼接和加法操作并打印出参数和返回值。
#include <stdio.h>
#include <string.h>
void a(char *p1, int p2);
int a_1(char *p1, int p2);
int a_1_1(char *p1, int p2);
void b(char *p1, int p2);
int b_1(char *p1, int p2);
void c(char *p1, int p2);
int main ()
{
while (1)
{
a("dtrace-test-in-a",100);
b("dtrace-test-in-b",200);
c("dtrace-test-in-c",300);
}
}
void a(char *p1, int p2)
{ char str[100];
int rst;
printf("a(%s,%d)\n",p1,p2);
strcpy(str,p1);
strcat(str,"&a_1");
rst=a_1(str,p2+10);
printf("a_1=%d\n",rst);
}
int a_1(char *p1, int p2)
{
int rst;
printf("a_1(%s,%d)\n",p1,p2);
rst=a_1_1(strcat(p1,"&a_1_1"),p2+1);
printf("a_1_1=%d\n",rst);
sleep(2);
return rst;
}
int a_1_1(char *p1, int p2)
{
int rst;
rst=p2+1;
printf("a_1_1(%s,%d)\n",p1,p2);
return rst;
}
void b(char *p1, int p2)
{ char str[100];
int rst;
strcpy(str,p1);
strcat(str,"&b_1");
printf("b(%s,%d)\n",p1,p2);
rst=b_1(str,p2+10);
printf("b_1=%d\n",rst);
}
int b_1(char *p1, int p2)
{
int rst;
rst=p2+1;
printf("b_1(%s,%d)\n",p1,p2);
sleep(3);
return rst;
}
void c(char *p1, int p2)
{
printf("c(%s,%d)\n",p1,p2);
}
2. 编译&运行此应用
root@IPS_TEST # gcc mydtrace.c -o mydtraced
root@IPS_TEST # ./mydtraced
a(dtrace-test-in-a,100)
a_1(dtrace-test-in-a&a_1,110)
a_1_1(dtrace-test-in-a&a_1&a_1_1,111)
a_1_1=112
a_1=112
b(dtrace-test-in-b,200)
b_1(dtrace-test-in-b&b_1,210)
b_1=211
c(dtrace-test-in-c,300)
a(dtrace-test-in-a,100)
a_1(dtrace-test-in-a&a_1,110)
3. 编写跟踪程序的探测脚本mydtrace,见mydrace.sh
#!/usr/sbin/dtrace -s
#pragma D option quiet
uint64_t last_timestamp;
pid$target:mydtraced::entry
{
last_timestamp = walltimestamp;
}
pid$target:mydtraced::return
{
t = (walltimestamp - last_timestamp) / 1000000;
printf("<--%s Spent %d ms\n", probefunc,t);
}
4. 运行此脚本,查看输出结果;初始统计有些不准确,需要忽略,后面的a_1,b_1准确的反映了耗时,当然由于它们分别被a,b调用,在a,b的调用统计上也有所反映。分析出瓶颈的关键所在之后,可以更有真对性处理。
root@IPS_TEST # ./mydtrace.sh -p `pgrep mydtraced`
<–b_1 Spent 1537253575408 ms
<–b Spent 1537253575408 ms
<–c Spent 0 ms
<–a_1_1 Spent 0 ms
<–a_1 Spent 1999 ms
<–a Spent 1999 ms
<–b_1 Spent 2999 ms
<–b Spent 2999 ms
<–c Spent 0 ms
<–a_1_1 Spent 0 ms
<–a_1 Spent 1999 ms
<–a Spent 1999 ms
<–b_1 Spent 3009 ms
<–b Spent 3009 ms
<–c Spent 0 ms
<–a_1_1 Spent 0 ms
^C
5. 分析系统性能瓶颈有时需要一些重要参数数据来协助诊断,比如文件名,分配的内存大小等,修改mydtrace.sh脚本
#!/usr/sbin/dtrace -s
#pragma D option quiet
pid$target:mydtraced:a_1:entry
{
printf("parameters pass into a_1:%s,%d\n",copyinstr(arg0),arg1);
}
6. 运行修改后的脚本,查看输出结果
root@IPS_TEST # ./mydtrace.sh -p `pgrep mydtraced`
parameters pass into a_1:dtrace-test-in-a&a_1,110
parameters pass into a_1:dtrace-test-in-a&a_1,110
^C