性能测试四项原则
一、实际项目中的性能测试才有意义
三个类别的基准:1.微观基准、2.宏观基准、3.折衷基准;
先尝试基于宏观基准的测试,了解整个系统以及代码是如何工作的,再使用微观基准作为性能的测量方法。
二、引入多样的测量方法来分析程序性能
1.批量执行所用时间的测量方法(耗时法)。注意,当应用程序中有使用缓存技术来获得更好的性能时,应先耗时法测量一遍,当缓存建立以后再测量。
2.吞吐量的测量方法。每秒钟操作数,又叫每秒事务(TPS)、每秒请求(RPS)、每秒操作数(OPS)。
3.响应时间的测量方法。客户端发出一个请求后直到接收到服务器的响应返回后的时间消耗。
三、多变性。
每次测量结果会随时间改变,即使使用相同数据,结果也可能不同。
不能简单的关注平均值,而是要使用统计分析的方法。
四、尽早测试、经常测试
1.提早准备测试用户以及测试环境的设计和创建;
2.考虑尽量用脚本来完成;
3.通过性能监控工具尽量收集可能得到的运行信息,为将来分析提供便利;
4.一定要在一个能真实模拟多数用户的机器环境下进行性能测试;
JAVA应用性能调优
Java 应用性能的瓶颈点非常多,比如磁盘、内存、网络 I/O 等系统因素,Java 应用代码,JVM GC,数据库,缓存等。笔者根据个人经验,将 Java 性能优化分为 4 个层级:
应用层、(需要理解代码逻辑,通过 Java 线程栈定位有问题代码行等)
数据库层、(需要分析 SQL、定位死锁等)
框架层、(需要懂源代码,理解框架机制)
JVM 层 (需要对 GC 的类型和工作机制有深入了解,对各种 JVM 参数作用了然于胸)
性能诊断工具
CPU诊断:对于 CPU 主要关注平均负载(Load Average),CPU 使用率,上下文切换次数(Context Switch)。
通过 top 命令可以查看系统平均负载和 CPU 使用率。
通过 vmstat 命令可以查看 CPU 的上下文切换次数。
使用 free –m 命令查看内存的使用情况。
通过 iostat 可以查看磁盘的读写情况,通过 CPU 的 I/O wait 可以看出磁盘 I/O 是否正常。
除了常用的 top、 ps、vmstat、iostat 等命令,还有其他 Linux 工具可以诊断系统问题,如 mpstat、tcpdump、netstat、pidstat、sar 等。
Java 应用诊断工具
jstack
jstack 命令通常配合 top 使用,通过 top -H -p pid 定位 Java 进程和线程,再利用 jstack -l pid 导出线程栈。由于线程栈是瞬态的,因此需要多次 dump,一般 3 次 dump,一般每次隔 5s 就行。将 top 定位的 Java 线程 pid 转成 16 进制,得到 Java 线程栈中的 nid,可以找到对应的问题线程栈。
JProfiler
JProfiler 可对 CPU、堆、内存进行分析,功能强大,如图 7 所示。同时结合压测工具,可以对代码耗时采样统计。
GC 诊断
jstat
jstat 命令可打印 GC 详细信息,Young GC 和 Full GC 次数,堆信息等。其命令格式为
jstat –gcxxx -t pid
jmap
jmap 打印 Java 进程堆信息 jmap –heap pid。通过 jmap –dump:file=xxx pid 可 dump 堆到文件,然后通过其它工具进一步分析其堆使用情况
MAT
MAT 是 Java 堆的分析利器,提供了直观的诊断报告,内置的 OQL 允许对堆进行类 SQL 查询,功能强大,outgoing reference 和 incoming reference 可以对对象引用追根溯源
坏代码特征:
(1)代码可读性差,无基本编程规范;
(2)对象生成过多或生成大对象,内存泄露等;
(3)IO 流操作过多,或者忘记关闭;
(4)数据库操作过多,事务过长;
(5)同步使用的场景错误;
(6)循环迭代耗时操作等。
数据库层的调优角度:
(1)在 SQL 语句层面进行优化:慢 SQL 分析、索引分析和调优、事务拆分等;
(2)在数据库配置层面进行优化:比如字段设计、调整缓存大小、磁盘 I/O 等数据库参数优化、数据碎片整理等;
(3)从数据库结构层面进行优化:考虑数据库的垂直拆分和水平拆分等;
(4)选择合适的数据库引擎或者类型适应不同场景,比如考虑引入 NoSQL 等。
总结
1)基础性能的调优
这里的基础性能指的是硬件层级或者操作系统层级的升级优化,比如网络调优,操作系统版本升级,硬件设备优化等。比如 F5 的使用和 SDD 硬盘的引入,包括新版本 Linux 在 NIO 方面的升级,都可以极大的促进应用的性能提升;
2)数据库性能优化
包括常见的事务拆分,索引调优,SQL 优化,NoSQL 引入等,比如在事务拆分时引入异步化处理,最终达到一致性等做法的引入,包括在针对具体场景引入的各类 NoSQL 数据库,都可以大大缓解传统数据库在高并发下的不足;
3)应用架构优化
引入一些新的计算或者存储框架,利用新特性解决原有集群计算性能瓶颈等;或者引入分布式策略,在计算和存储进行水平化,包括提前计算预处理等,利用典型的空间换时间的做法等;都可以在一定程度上降低系统负载;
4)业务层面的优化
技术并不是提升系统性能的唯一手段,在很多出现性能问题的场景中,其实可以看到很大一部分都是因为特殊的业务场景引起的,如果能在业务上进行规避或者调整,其实往往是最有效的。
参考文档
https://www.ibm.com/developerworks/cn/java/j-lo-java-performance-testing/index.html
https://www.ibm.com/developerworks/cn/java/j-lo-performance-tuning-practice/index.html