zoukankan      html  css  js  c++  java
  • 一次java性能调优总结

       我们的系统中新开发了一个数据抽取的功能,东西做完后,一看执行时间那叫一个恼火。参考同类系统同样功能的执行时间,目标:将本地数据处理时间压缩到5秒以内。

       

      第一步:

       要想知道哪个地方需要优化,仅凭感觉还是不够,我使用btrace寻找速度慢点原因。下面贴出这次使用的btrace代码:

    import static com.sun.btrace.BTraceUtils.name;  
    import static com.sun.btrace.BTraceUtils.print;  
    import static com.sun.btrace.BTraceUtils.println;  
    import static com.sun.btrace.BTraceUtils.probeClass;  
    import static com.sun.btrace.BTraceUtils.probeMethod;  
    import static com.sun.btrace.BTraceUtils.str;  
    import static com.sun.btrace.BTraceUtils.strcat;  
    import static com.sun.btrace.BTraceUtils.timeMillis;  
      
    import com.sun.btrace.annotations.BTrace;  
    import com.sun.btrace.annotations.Kind;  
    import com.sun.btrace.annotations.Location;  
    import com.sun.btrace.annotations.OnMethod;  
    import com.sun.btrace.annotations.TLS;  
      
    /** 
     * 监控方法耗时 
     *  
      */  
    @BTrace  
    public class PrintTimes {  
      
        /** 
         * 开始时间 
         */  
        @TLS  
        private static long startTime = 0;  
      
        /** 
         * 方法开始时调用 
         */  
        @OnMethod(clazz = "com.xxx.service.XXService", method = "/.+/")  
        public static void startMethod() {  
            startTime = timeMillis();  
        }  
      
        /** 
         * 方法结束时调用<br> 
         */  
        @SuppressWarnings("deprecation")  
        @OnMethod(clazz = "com.xxx.service.XXService", method = "/.+/", location = @Location(Kind.RETURN))  
        public static void endMethod() {  
      
            print(strcat(strcat(name(probeClass()), "."), probeMethod()));  
            print("  [");  
            print(strcat("Time taken : ", str(timeMillis() - startTime)));  
            println("]");  
        }  
    }

    本段代码会匹配 com.xxx.service.XXService 类中的所有方法,打印每个方法的执行时间,每调用一次会打印一次,不是总时间。更多BTrace内容请访问官网:https://kenai.com/projects/btrace

    第二步到了这一步已经知道了速度慢集中在哪些点。对于这个系统我可以做哪些工作来优化呢?

    1.代码方面调整
       a.并行化  (关于线程池线程数量的调整,请参考我的另外一篇关于"设置最优线程数"的文章)
       b.增加缓存
    c.插入操作执行频繁的地方,用原生sql进行批量插入(持久化层使用EclipseLink)
    d.避免大数据量表join操作
    2.参数调整 a.JVM内存参数 b.数据库连接池参数

    3.功能实现设计调整 (最不愿看到的)

    根据实际情况采取相应手段调整。

    第三步

      检测优化后系统该功能性能情况,如果有效则保留,否则恢复代码到本次优化之前的那个状态。

    第三步结束后,继续执行第一、二、三步。直到性能达到预期要求。

    根据对待优化代码进行分析,最后采用了并行化,增加缓存以及批量插入优化的操作。软件参数和功能设计方面不需要调整。

    --------------- 问题纪录 -------------

    在将插入操作改成批量插入时,日志报以下错误:

    Caused by: org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot get a connection, pool error Timeout waiting for idle object
    14:45:03.821 [pool-1-thread-2] ERROR java.lang.Throwable -     at org.apache.tomcat.dbcp.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:114)
    14:45:03.822 [pool-1-thread-2] ERROR java.lang.Throwable -     at org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
    14:45:03.822 [pool-1-thread-2] ERROR java.lang.Throwable -     at org.eclipse.persistence.sessions.JNDIConnector.connect(JNDIConnector.java:123)
    14:45:03.822 [pool-1-thread-2] ERROR java.lang.Throwable -     ... 39 more
    14:45:03.823 [pool-1-thread-2] ERROR java.lang.Throwable - Caused by: java.util.NoSuchElementException: Timeout waiting for idle object

    有几个思路:
    1.数据库连接没有成功释放;(得到数据库连接池的监控数据,可以实时看到空闲连接的情况)
    2.数据库连接成功释放,但是由于多个线程同时抢占连接而导致有些线程抢不到连接。(这个情况考虑增大数据库连接池) 

    使用BTrace监控连接池发现只有获得连接没有释放连接操作,看来属于1。由于使用EclipseLink以为 entityManager.close()可以释放连接,经过查阅EclipseLink官网文档,原来是使用不当,下面是获取连接的详细信息,:

    JPA 2.0
    entityManager.getTransaction().begin();
    java.sql.Connection connection = entityManager.unwrap(java.sql.Connection.class);
    ...
    entityManager.getTransaction().commit();

    最后在finally将connection.close()。

  • 相关阅读:
    h5+app 开启位置服务
    HDFS 修改默认副本数
    Flink学习之路(二)Flink搭建(单机)
    Flink学习之路(一)Flink简介
    HDFS中大数据常见运维指令总结
    hive 将hive表数据查询出来转为json对象和json数组输出
    linux下 shell时间处理
    Elasticsearch分页解决方案
    intelliJ IDEA自动优化导入包
    sql server 登录名和用户名的区别和联系
  • 原文地址:https://www.cnblogs.com/bobsha/p/6252878.html
Copyright © 2011-2022 走看看