性能测试之性能调优

本文详细探讨了性能测试中的性能调优步骤,包括评估指标、前置条件、优化思路和常见问题及其解决方案。强调了数据库性能、SQL优化、线程管理、内存泄漏和JVM垃圾回收的重要性。此外,提供了实用的命令行工具帮助定位和解决性能问题,并提出了软件架构、业务流程和数据库层面的优化建议。
摘要由CSDN通过智能技术生成

前言

性能调优,无疑是个庞大的话题,也是很多项目中非常重要的一环,性能调优难做是众所周知的,毕竟性能调优涵盖的面实在是太多了,在这里我们蜻蜓点水般的来看看性能调优这项庞大的工程都有些什么过程,同时也看看这些过程中常见的一些做法。

一、应用系统性能评价指标

响应时间:尽快的给用户返回响应,体现系统处理请求的速度;
吞吐量TPS:每秒完成的事务数,体现系统处理能力;
并发性:业务请求高并发时,系统能否稳定运行;
扩展性:单机处理能力不足时,系统能否横向扩展。
TPS = 并发用户数 / 响应时间
<说明>
业界衡量一个软件系统性能的三个指标:TPS(Transactions Per Second),QPS(Query Per Second)以及RT(Response Time),其实前二者可以等价于写操作和读操作。如此说来,系统性能优化无非是提升读写的效率,对应到实际应用场景就是增加系统的吞吐量,最终对于用户的直观感受就是较低的响应时延。
性能测试常见指标:https://blog.csdn.net/cainiaoxuhongxia/article/details/128929527?spm=1001.2014.3001.5501

二、性能测试前置条件

1、数据库表数据量准确

要和生产数据量保持一致,至少一个数量级。数据分布尽量均匀。

2、测试环境和生产一致

测试环境机器配置、参数、代码尽可能和生产保持一致(数据库服务器硬件除外)。

3、合理确定并发用户量

系统并发用户量有多种算法可以估算:
平均并发用户数:
C=nL/T(n是考察时间内用户登录数,L是用户平均在线时间长度,T是考察值时间长度)
并发用户数峰值:C’=C + 3根号C
用户总量/统计时间影响因子:
网银用户量100万,根据2/8原则, 80%用户在上午9点到11点,下午2点到4点之间登录系统,每次登录耗时1到1.5秒。则并发用户为:
10000000.8/4/36001.5=82.5,
10000000.8/4/36001=55
根据系统用户数计算:
并发用户数=系统最大在线用户数的8%到12%
根据TPS估计:
C=(Think Time + 1)* TPS,
网银用户思考时间10s,
C=(10+1)* 3=33。

4、预估各功能交易量,确定压测功能优先级

根据交易量从大到小排名,排名靠前的优先压测。

5、设置性能问题认定标准(性能指标:需求为准)

比如响应时间超过3s、TPS低于10、服务器cpu占用率超过70%、jvm堆内存使用100%、垃圾回收频繁、网络IO或磁盘IO达到瓶颈等……都可能是性能问题。

三、性能优化一般思路

1、找到性能瓶颈

性能瓶颈定义:导致系统TPS低、响应时间长、资源(CPU、内存、网络)占用高等问题的关键程序模块。提升该程序模块的性能,可以大幅度改善性能。
常见的性能瓶颈原因包括:数据库慢查询SQL、日志打印、xml大报文解析和格式转换、复杂业务逻辑、锁竞争等。

2、如何找到性能瓶颈

使用LoadRunner给每个接口的增加事务,记录其响应时间和TPS,最慢的那个接口往往是瓶颈;
分析慢操作的日志,查看是哪个操作耗时最长;
分析数据库快照,看是否有执行较慢或者全表扫描的SQL;
通过Javacore查看线程正在执行的代码,是大部分阻塞在IO上,还是大部分在进行计算。针对不同的问题,使用不同的分析工具。
<说明:>
Javacore 是一个当前 JVM 运行状态的快照。通过对 Javacore 的分析,可以了解在 JVM 中运行的应用程序的当前状态,比如是否“卡”在某一点上,或在某些代码上运行时间太长。

3、针对性能瓶颈进行合理优化

性能优化原则:
先优化瓶颈问题;
方案简单,尽量不引入更多复杂性,尽量不降低业务体验;
满足系统性能要求即可,不引入新的bug。

四、常见问题及优化方法

1、应用代码相关

遇到性能问题,首先做的是检查否与业务代码相关——不是通过阅读代码解决问题,而是通过日志或代码,排除掉一些与业务代码相关的低级错误
性能优化的最佳位置是应用内部,比如:
查看业务日志,检查日志内容里是否有大量的报错产生,应用层、框架层的一些性能问题,大多数都能从日志里找到端倪(日志级别设置不合理,导致线上疯狂打日志)
检查代码的主要逻辑,如for循环的不合理使用、NPE、正则表达式、数学计算等常见的一些问题,都可以通过简单地修改代码修复问题
别动辄就把性能优化和缓存、异步化、JVM 调优等名词挂钩,复杂问题可能会有简单解
了解一些基本的代码常用踩坑点,可以加速问题分析思路的过程,从CPU、内存、JVM等分析到的一些瓶颈点优化思路,也有可能在代码这里体现出来
下面是一些高频的,容易造成性能问题的编码要点
1)正则表达式非常消耗CPU(如贪婪模式可能会引起回溯),慎用字符串的split()、replaceAll()等方法,正则表达式一定预编译
2)String.intern()在低版本(Java 1.6 以及之前)的 JDK 上使用,可能会造成方法区(永久代)内存溢出。在高版本JDK 中,如果string pool设置太小而缓存的字符串过多,也会造成较大的性能开销
3)输出异常日志时,如果堆栈信息是明确的,可以取消输出详细堆栈,异常堆栈的构造是有成本的
注意:同一位置抛出大量重复的堆栈信息,JIT会将其优化后成,直接抛出一个事先编译好的、类型匹配的异常,异常堆栈信息就看不到
4)避免引用类型和基础类型之间无谓的拆装箱操作,尽量保持一致,自动装箱发生太频繁,会非常严重消耗性能
5)Stream API的选择
复杂和并行操作,推荐使用Stream API可以简化代码,同时发挥来发挥出CPU多核的优势,如果是简单操作或者CPU是单核,推荐使用显式迭代
6)根据业务场景,通过ThreadPoolExecutor手动创建线程池
结合任务的不同,指定线程数量和队列大小,规避资源耗尽的风险,统一命名后的线程也便于后续问题排查
7)根据业务场景,合理选择并发容器
如选择Map类型的容器:
a. 如果对数据要求有强一致性,可使用Hashtable或者Map +锁
b. 读远大于写,使用CopyOnWriteArrayList
c. 存取数据量小、对数据没有强一致性的要求、变更不频繁的,使用ConcurrentHashMap
d. 存取数据量大、读写频繁、对数据没有强一致性的要求,使用ConcurrentSkipLi

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值