---
title: 使用Java-Perf进行性能调优提高tps-官方技术文章-鲲鹏社区
description: 本文将以一个真实的调优案例来向大家展示如何使用 DevKit Java-Perf 调优工具进行性能问题的定位和调优
keywords: Java,Perf,进行性能调优,提高,官方技术文章,鲲鹏社区,背景,采集热点火焰
url: https://www.hikunpeng.com/developer/techArticles/20251205-22?envFlag=1
section: (其他)
---

# 使用Java-Perf进行性能调优提高tps-官方技术文章-鲲鹏社区

URL: https://www.hikunpeng.com/developer/techArticles/20251205-22?envFlag=1
描述: 本文将以一个真实的调优案例来向大家展示如何使用 DevKit Java-Perf 调优工具进行性能问题的定位和调优
关键词: Java,Perf,进行性能调优,提高,官方技术文章,鲲鹏社区,背景,采集热点火焰

官方技术文章 [了解详情](https://www.hikunpeng.com/zh/developer/techArticles)

使用Java-Perf进行性能调优提高tps

使用Java-Perf进行性能调优提高tps

性能调优

发表于 2025/12/05

0

# 背景

XXXX项目在线填报用例 tps 为 3.6/sec，不符合预期，希望进行调优。

在线填报用例分为预览 和 上报两个接口，其中预览接口的tps远大于 3.6，

瓶颈是上报接口。

50并发是上报接口tps最优的并发数， tps 为 5.6/sec，均耗时为 8.9s

单并发上报接口 tps 为 1/sec，平均耗时为 1s

并发高的情况下，上报接口耗时增多了将近8倍，但是 tps 提升的不多。各项系统资源使用率都不高，无瓶颈。

接下来的调优重点是分析接口耗时大幅度增多的原因，降低耗时，从而提升tps

# 1、采集热点火焰图&锁火焰图

## 热点火焰图

热点函数OnlineFillController.largeAmountReport是报送接口的入口函数，

Jvm内部代码编译操作以及GC相关操作也属于热点操作

接下来可通过java调优工具分析下对应程序的线程状态、GC执行情况，对largeAmountReport进行插桩，具体分析其调用链的耗时。

## 锁火焰图

大部分锁是日志打印相关的锁，可通过java调优工具分析线程的锁情况。

# 2、分析GC活动

50并发

1并发

分析java工具采集的GC活动数据，GC频率比较均匀，垃圾回收耗时也不高，耗时也没有随着并发的增高也明显变大。

# 3、分析线程状态&线程锁竞争情况

50并发

通过java工具在线分析-概览发现，在50并发压测下，程序80%的线程会处于等待状态。

## 锁分析

通过锁图和统计分析，60个业务线程中有42个线程会因为竞争同一把锁而处于等待状态。

根据调用栈发现这把锁处于从druid数据库连接池中获取数据库连接的操作中。

可通过java工具抓取应用的SQL执行情况；

分析org.springframework.jdbc.datasource.DataSourceUtils.fetchConnection获取数据库连接的函数在低并发和高并发情况下的耗时。

# 4、分析SQL语句执行情况

## 1并发压测

## 50并发压测

通过java工具采集SQL执行情况，经分析耗时最长的一个SQL查询语句，50并发和单并发对比，耗时增加了0.4s左右，其他SQL语句耗时基本没变。

对于1s到9s的报送接口耗时倍增情况，执行SQL语句增加的耗时只能占小部分。

# 5、关键函数调用链耗时分析

## DataSourceUtils.fetchConnection 函数

1并发

50并发

获取数据库连接操作的耗时，随着并发的提高耗时会明显增大，0.001 ms -> 589ms

该操作内部涉及锁竞争，说明随着并发的提高，锁竞争也会越激烈。

通过第四步的采集数据得知一次报送操纵会涉及9条SQL语句的执行。

我们假定一次报送每条SQL执行一次，那么就会有从数据库连接池中拿9次数据库连接的动作，我们以1并发和50并发为例，（589-0.001）* 9 / 1000 = 5.3s，

50并发情况下，一次报送操作，光在获取数据库连接的耗时上就多了5.3s，

5.3s对于整体的耗时占比比重也较大，约为58%。

降低获取数据库连接的耗时，是个重要的调优方向。

# 分析数据库连接池参数

通过采集的数据得知，该应用druid数据库连接池的最大连接为8，它代表这个连接池最多创建8个数据库连接供应用使用。

那么在并发50的情况下，最多只有8个线程能拿到数据库连接去跟数据库做交互，其他的线程都得排队等待。这一点能跟第三步的分析对得上。

适当调高这个数据库连接数的上限，能同时拿到数据库连接的线程就会变多，排队等待的线程就会减少。理论上获取数据库连接的操作耗时也会响应减少。

接下来做验证。

# 6、调高数据库连接池的最大连接数进行验证

## 启动参数调整数据库连接数

通过启动参数-Dspring.datasource.druid.max-active调整druid数据库连接池的最大连接数

## 压测

经过不断调整并发数和数据库连接池数作压测验证，60并发和60数据库连接数的组合下tps最佳，tps从5.6 / sec提高到18 / sec，耗时也从8.9s降低到3.2s

这个效果是很明显的。

## 线程状态

等待状态的线程比例从80%降低到44%

## 锁分析

有31个业务线程因等待获取锁而处于阻塞或等待状态，占比为50%，

但是等待锁变为了两把，而且都是跟lockback插件打印日志有关，不再是之前的获取数据库连接相关的锁

## 关键函数耗时

DataSourceUtils-fetchConnection:

获取数据库连接耗时从589ms降低到0.003ms，接近单并发的耗时。

## SQL语句耗时

60并发60数据库连接：

60并发8数据库连接：

SQL语句的耗时比50并发的耗时明显增多

这不难理解，数据库连接变多，那么跟数据库的操作就会变得更频繁，数据的压力就会变大，

相关SQL执行时间变长也是比较正常的。

## 关键进程资源变化

### 报送业务进程

50并发8数据库连接：

60并发60数据库连接：

报送进程cpu使用率从35%升高到94%

### Mysql进程

50并发8数据库连接：

60并发60数据库连接：

mysql进程cpu使用率从763%升高到2000%，压力明显增加

## 总结

通过第六步的验证结果及相关指标的变化，可以得出调高druid数据库连接池的最大连接数，

在并发高的情况下减轻业务线程获取数据库连接的压力，规避排队等待获取数据库连接的现象。

# 调优方案&优化结果

调高druid数据库连接池的最大连接数到60

报送接口tps从5.6 / sec提高到18 / sec，耗时也从8.9s降低到3.2s

在线填报用例tps从3.6 / sec提高到18 / sec

# 案例总结

1、针对吞吐量调优（tps、qps等），如果随着并发的提高，发现吞吐量明线不是线性升高的趋势，可以怀疑是不是业务中有同步锁的操作。

2、性能调优一定要从问题最大的点出发，这样调优后收益往往是最大的。

本案例来讲，报送接口单并发下耗时为1s，tps为1 / sec，假设报送逻辑是并行的，互不影响，在理想（资源足够并且无其他干扰因素）情况下，5并发tps应该可以到5/ sec，10并发tps应该可以到10/ sec。但是经过压测50并发tps最高只有5.6 / sec，缩水有点严重，可以怀疑是不是存在同步阻塞的操作，让并行变成了串行或者其他的资源瓶颈导致的。还有一点耗时从1s增加到8.9s，增大比例有点多。

从上述现象看，调优重点是分析下锁看是否存在同步阻塞操作；分析下耗时增大明显的原因；分析是否出现资源瓶颈。

本页内容
