我们的系统中新开发了一个数据抽取的功能,东西做完后,一看执行时间那叫一个恼火。参考同类系统同样功能的执行时间,目标:将本地数据处理时间压缩到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()。


一次java性能调优总结的更多相关文章

  1. Java性能调优笔记

    Java性能调优笔记 调优步骤:衡量系统现状.设定调优目标.寻找性能瓶颈.性能调优.衡量是否到达目标(如果未到达目标,需重新寻找性能瓶颈).性能调优结束. 寻找性能瓶颈 性能瓶颈的表象:资源消耗过多. ...

  2. Java性能调优(一):调优的流程和程序性能分析

     https://blog.csdn.net/Oeljeklaus/article/details/80656732 Java性能调优 随着应用的数据量不断的增加,系统的反应一般会越来越慢,这个时候我 ...

  3. Java性能调优:利用JMC分析性能

    Java性能调优作为大型分布式系统提供高性能服务的必修课,其重要性不言而喻. 好的分析工具能起到事半功倍的效果,利用分析利器JMC.JFR,可以实现性能问题的准确定位. 本文主要阐述如何利用JMC分析 ...

  4. Java性能调优:利用JFR生成性能日志

    Java性能调优作为大型分布式系统提供高性能服务的必修课,其重要性不言而喻. 好的分析工具能起到事半功倍的效果,利用分析利器JMC.JFR,可以实现性能问题的准确定位. 本文主要阐述如何利用JFR生成 ...

  5. 第六章 Java性能调优工具(待续)

    Java性能调优工具 Windows工具 JDK命令行工具 JConsole工具 Visual VM多合一工具 Visual VM对QQL的支持 MAT内存分析工具 MAT对QQL的支持 JProfi ...

  6. java 性能调优和GC

    JAVA 性能调优和GC http://blog.csdn.net/gzh0222/article/details/7663181 JAVA GC调优手记 http://blog.csdn.net/f ...

  7. Java性能调优概述

    目录 Java性能调优概述 性能优化有风险和弊端,性能调优必须有明确的目标,不要为了调优而调优!!!盲目调优,风险远大于收益!!! 程序性能的主要表现点 执行速度:程序的反映是否迅速,响应时间是否足够 ...

  8. Java性能调优攻略全分享,5步搞定!(附超全技能图谱)

    对于很多研发人员来说,Java 性能调优都是很头疼的问题,为什么这么说?如今,一个简单的系统就囊括了应用程序.数据库.容器.操作系统.网络等技术,线上一旦出现性能问题,就可能要你协调多方面组件去进行优 ...

  9. Java性能调优实战,覆盖80%以上调优场景

    Java 性能调优对于每一个奋战在开发一线的技术人来说,随着系统访问量的增加.代码的臃肿,各种性能问题便会层出不穷. 日渐复杂的系统,错综复杂的性能调优,都对Java工程师的技术广度和技术深度提出了更 ...

  10. Java性能调优

    一.JVM内存模型及垃圾收集算法 1.根据Java虚拟机规范,JVM将内存划分为: New(年轻代) Tenured(年老代) 永久代(Perm) 其中New和Tenured属于堆内存,堆内存会从JV ...

随机推荐

  1. Select For update语句浅析 (转)

    Select … for update语句是我们经常使用手工加锁语句.通常情况下,select语句是不会对数据加锁,妨碍影响其他的DML和DDL操作.同时,在多版本一致读机制的支持下,select语句 ...

  2. HTA全解析:给VBS和JS一个强大的交互界面

    1.概述 HTA全称Html Application,在Windows中由mshta.exe加载执行,是一种本地程序.可使用html元素来构建界面,用JS或VBS来构建执行逻辑,从而强化Windows ...

  3. ABP dynamic API

    打开ABP的事例项目SimpleTaskSystem.WebSpaAngular 中LayoutView <!-- Dynamic scripts of ABP system (They are ...

  4. Django(四)

    一.请求周期 url> 路由 > 函数或类 > 返回字符串或者模板语言? 1.Form表单提交: 提交 -> url > 函数或类中的方法 - .... HttpResp ...

  5. Android 6.0 权限请求

    在申请权限之前一定要在清单配置文件中添加该权限private static final int MY_PERMISSIONS_REQUEST_RECORD_AUDIO = 1; //随便定义 publ ...

  6. Linux下面配置文件~/.bash_profile

    ~/.的意义是什么? ~ 代表你的/home/用户名目录 假设你的用户名是x,那么~/就是/home/x/ . 是代表此目录本身,但是一般可以不写 所以cd ~/. 和cd ~ 和cd ~/效果是一样 ...

  7. INNO SETUP 读取可变注册表路径的问题

    ;INNO 读取可变注册表路径的问题 ;问题:;我想自动为 FireFox 安装上 Real 的 Mozilla 插件~但是它的路径存放在"HKEY_CURRENT_USER\Softwar ...

  8. FireMonkey 保存图片到JPG的方法 BMP转JPG

    习惯VCL的做法了,到了FireMonkey里面,好像查不到单独的JPEG单元了,不少朋友就郁闷如何处理JPG了,这么大件事,不可能没有处理方法的,具体就请看代码: uses FMX.Surfaces ...

  9. 接触Matlab5年一个总结(Matlab要掌握的一些要点 )

    阅读目录 前言 Matlab的开发环境与简单介绍 Matlab的常见命令 Matlab的灵魂-矩阵操作 Matlab的.m或.fig的编程与技巧 从大二开始接触到matlab,讲真,这是一个我觉得很良 ...

  10. window7 x64 path

    %SystemRoot%\system32; %SystemRoot%; %SystemRoot%\System32\Wbem; %SYSTEMROOT%\System32\WindowsPowerS ...