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


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

        工具是为测试目标服务的,关键是分析的方法和思路,在项目中积累经验,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 " 7777
    ka
    3.打印线程堆栈信息:
    [root@localhost logs]# jstack 8792|grep ka -A 30

     

    为什么是这么个分析过程呢,我们反向来解析,研究代码层的情况,可能多你理解更加有效。如果大家对课程感兴趣可以到poptest.cn咨询,欢迎大家来咨询课程

    一.假想资源问题:
    新接一个项目,只有老大和小弟俩人来干。
    但是俩人都需要休息,只有一个休息的房间(共享的资源)。
    老板和小弟轮流休息,老大一周休息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就会被一个线程独占,可能导致程序可能很长时间没有响应等等
    原文链接:http://www.cnblogs.com/laoli0201

  • 相关阅读:
    java 笔记 Thread.currentThread().getContextClassLoader() 和 Class.getClassLoader()区别
    JAVA 笔记 ClassLoader.getResourceAsStream() 与 Class.getResourceAsStream()的区别
    配置mabatis,报Could not load driverClass ${jdbc.driverClassName}
    maven-配置文件配置src/resource下的文件
    eclipse中tomcat 中server location灰色,如何修改?
    解决maven项目update project会更改jdk版本问题
    maven创建web工程Spring配置文件找不到问题解决方案
    maven:pom.xml中没有dependency标签错误
    [转载]如何让上传到新浪博客和相册中的照片更大更清晰
    [转载]如何让上传到新浪博客和相册中的照片更大更清晰
  • 原文地址:https://www.cnblogs.com/poptest/p/4874915.html
Copyright © 2020-2023  润新知