天天看点

老李分享:应用程序性能瓶颈定位方法和原理

老李分享:应用程序性能瓶颈定位方法和原理

    工具是为测试目标服务的,关键是分析的方法和思路,在项目中积累经验,poptest是业内唯一一家培养测试开发工程师的机构,在培训中遴选了大量的案例,通过案例来帮助学员提高自动化测试经验,性能测试经验,

问题:

      程序运行的服务器cpu使用率很高,96%左右的使用率

分析: 

1,程序属于CPU密集型,(可以看我前面的文章)。 

2,程序代码问题,死循环。 

定位: 

1,通过top命令,PID显示8792的Java进程占用CPU高达98%。 

2,定位线程或代码,显示线程列表,并按照CPU占用高的线程排序: 

[root@localhost logs]# ps -mp 8792-o THREAD,tid,time | sort -rn 

显示结果如下: 

USER     %CPU PRI SCNT WCHAN  USER SYSTEM   TID     TIME 

root        10.5  19    - -         -      -  6665 00:15:46 

root        10.1  19    - -         -      -  6666 00:15:54 

找到了耗时最高的线程6665,占用CPU时间有??分钟了! 

将需要的线程ID转换为16进制格式: 

[root@localhost logs]# printf "%x\n" 7777 

ka

3.打印线程堆栈信息: 

[root@localhost logs]# jstack 8792|grep ka -A 30

一.假想资源问题:

新接一个项目,只有老大和小弟俩人来干。

但是俩人都需要休息,只有一个休息的房间(共享的资源)。

老板和小弟轮流休息,老大一周休息

5

天,小弟一周休息

2

天,

如此干了

100

周,项目结束。(资源共享)

处理这个两个线程共享休息室问题

二.代码实现:

package

javaAdvanced;

/**

* @auther cuiH

* Date: 13-10-23

*/

public

class

TraditionalThreadCommunication {

public

static

void

main(String[] args) {

final

RestRoom restRoom = 

new

RestRoom();          

//进行调用

new

Thread(

new

Runnable() {

@Override

public

void

run() {

//子线程进行50个10循环

for

(

int

i = 

1

; i <= 

100

; i++) {

/**

* 字节码进行加锁TraditionalThreadCommunication.class 最简单的方式

* 可以使用,但是不适合比较大的程序

* 采用面向对象的方式,将相关联的方法处理为一个对象

* filter拦截就是一种同步机制

*/

//                            synchronized (TraditionalThreadCommunication.class) {

//                                for (int j = 1; j <= 10; j++) {

//                                    System.out.println("sub thread sequence " + i + " loop of " + j);

//                                }

//                            }

try

{

restRoom.coder(i);

catch

(InterruptedException e) {

e.printStackTrace();

}

}

}

}

).start();

//main线程进行50 个循环

for

(

int

i = 

1

; i <= 

100

; i++) {

try

{

restRoom.boss(i);

catch

(InterruptedException e) {

e.printStackTrace();

}

}

}

}

class

RestRoom {

private

boolean

bShouldBoss = 

true

;

//锁,相当于信号量机制的信号量

public

synchronized

void

coder(

int

i) 

throws

InterruptedException {

if

(!bShouldBoss) {

this

.wait();                 

//等待

}

for

(

int

j = 

1

; j <= 

2

; j++) {

System.out.println(

"小弟休息第 "

+ j + 

" 天,第"

+ i + 

" 次休息"

);

}

bShouldBoss = 

false

;

this

.notify();

//唤醒进程

}

public

synchronized

void

boss(

int

i) 

throws

InterruptedException {

if

(bShouldBoss) {

this

.wait();                           

//等待

}

for

(

int

j = 

1

; j <= 

5

; j++) {

System.out.println(

"老大休息第 "

+ j + 

" 天,第"

+ i + 

" 次休息"

);

}

bShouldBoss = 

true

;

this

.notify();

}

}

三.输出

小弟休息第 

1

天,第

1

次休息

小弟休息第 

2

天,第

1

次休息

老大休息第 

1

天,第

1

次休息

老大休息第 

2

天,第

1

次休息

老大休息第 

3

天,第

1

次休息

老大休息第 

4

天,第

1

次休息

老大休息第 

5

天,第

1

次休息

小弟休息第 

1

天,第

2

次休息

小弟休息第 

2

天,第

2

次休息

老大休息第 

1

天,第

2

次休息

老大休息第 

2

天,第

2

次休息

老大休息第 

3

天,第

2

次休息

老大休息第 

4

天,第

2

次休息

老大休息第 

5

天,第

2

次休息

。。。

。。。

小弟休息第 

1

天,第

100

次休息

小弟休息第 

2

天,第

100

次休息

老大休息第 

1

天,第

100

次休息

老大休息第 

2

天,第

100

次休息

老大休息第 

3

天,第

100

次休息

老大休息第 

4

天,第

100

次休息

老大休息第 

5

天,第

100

次休息

四.大家假想下前面性能分析的案例:

    在这个代码里,如果把老大的休息日的代码写错了写成了死循环,会怎么样,那么这个线程就会不断执行下去,而另外一个线程会出现无限等待。cpu就会被一个线程独占,可能导致程序可能很长时间没有响应等等