使用arthas进行代码优化
使用 进行 代码优化 arthas
2023-06-13 09:14:24 时间
今天接到了客户反应的远程医疗系统的BUG,解决了BUG的同时,顺带发现这里除了bug之外方法执行很慢,觉得顺带优化一下。记录一下优化过程。
首先我们目标很明确,根据调用栈统计每个调用所用的时间,然后再去具体找到具体的慢代码所在的位置。
1、使用的工具是阿里的Arthas的trace命令。
2、启动arthas,并找到相关的java进程,输入service的类名和方法名 ,开启调用统计。
trace com.rest.server.service.InstitutionUserServiceImpl addDoctorUser
3、输入后,到程序中调试,让程序中该业务场景复现一次,并观察arthas的控制台。
[arthas@52935]$ trace com.rest.server.service.InstitutionUserServiceImpl addDoctorUser
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 882 ms, listenerId: 1
`---ts=2022-08-28 23:21:49;thread_name=http-nio-8081-exec-12;id=54;is_daemon=true;priority=5;TCCL=org.apache.catalina.loader.ParallelWebappClassLoader@4305e569
`---[30508.997167ms] com.rest.server.service.InstitutionUserServiceImpl:addDoctorUser()
+---[0.09% 28.840916ms ] com.rest.server.service.InstitutionUserServiceImpl:get() #176
+---[0.04% 12.467833ms ] com.haiseer.edu.domain.core.MInstitutionUser:getInstitution() #176
+---[87.74% 26767.496625ms ] com.rest.server.service.InstitutionUserServiceImpl:verifyUserName() #178
+---[0.00% 0.04375ms ] com.rest.server.service.InstitutionUserServiceImpl$5:<init>() #186
+---[0.37% 114.200791ms ] com.haiseer.edu.domain.core.MDoctorDAO:create() #186
+---[0.00% 0.014417ms ] com.rest.server.service.InstitutionUserServiceImpl$6:<init>() #215
+---[0.05% 15.798875ms ] com.haiseer.edu.domain.core.MInstitutionDoctorUserDAO:create() #215
+---[0.02% 7.126875ms ] com.haiseer.edu.domain.core.MInstitutionDoctorUser:getInstitution() #238
+---[0.07% 22.163417ms ] com.hsr.util.HSUtil:query() #239
+---[0.00% 0.01225ms ] com.haiseer.edu.domain.core.MInstitution:getUuid() #240
+---[0.00% 0.02275ms ] org.hibernate.Query:setParameter() #240
+---[0.00% 0.005291ms ] org.hibernate.Query:setParameter() #241
+---[0.08% 23.364834ms ] org.hibernate.Query:uniqueResult() #242
+---[0.00% 0.021667ms ] com.haiseer.edu.domain.core.MInstitutionDoctorUser:setInstitutionRole() #243
`---[0.01% 2.707083ms ] com.rest.server.service.InstitutionUserServiceImpl:saySuccess() #245
可以看到,统计结果显示一共花了30508.997167ms,将近30秒钟…实在太慢了,而且调用时间大部分都浪费在InstitutionUserServiceImpl:verifyUserName这个方法上了。
4、找到程序中对应的点具体问题具体分析去优化
在代码中找到verifyUserName这个方法的问题,再去细看后发现是n+1次查询问题,修改解决。
5、测试修改后的效果:
`---ts=2022-08-28 23:46:40;thread_name=http-nio-8081-exec-13;id=55;is_daemon=true;priority=5;TCCL=org.apache.catalina.loader.ParallelWebappClassLoader@4305e569
`---[377.296708ms] com.rest.server.service.InstitutionUserServiceImpl:addDoctorUser()
+---[0.86% 3.247375ms ] com.rest.server.service.InstitutionUserServiceImpl:get() #176
+---[0.94% 3.532208ms ] com.haiseer.edu.domain.core.MInstitutionUser:getInstitution() #176
+---[78.55% 296.379708ms ] com.rest.server.service.InstitutionUserServiceImpl:verifyUserName() #178
+---[0.01% 0.032959ms ] com.rest.server.service.InstitutionUserServiceImpl$5:<init>() #186
+---[8.19% 30.918583ms ] com.haiseer.edu.domain.core.MDoctorDAO:create() #186
+---[0.01% 0.038666ms ] com.rest.server.service.InstitutionUserServiceImpl$6:<init>() #215
+---[3.73% 14.081791ms ] com.haiseer.edu.domain.core.MInstitutionDoctorUserDAO:create() #215
+---[1.38% 5.208292ms ] com.haiseer.edu.domain.core.MInstitutionDoctorUser:getInstitution() #238
+---[0.03% 0.120333ms ] com.hsr.util.HSUtil:query() #239
+---[0.00% 0.004583ms ] com.haiseer.edu.domain.core.MInstitution:getUuid() #240
+---[0.01% 0.031542ms ] org.hibernate.Query:setParameter() #240
+---[0.00% 0.005583ms ] org.hibernate.Query:setParameter() #241
+---[5.73% 21.62025ms ] org.hibernate.Query:uniqueResult() #242
+---[0.00% 0.017584ms ] com.haiseer.edu.domain.core.MInstitutionDoctorUser:setInstitutionRole() #243
`---[0.17% 0.658083ms ] com.rest.server.service.InstitutionUserServiceImpl:saySuccess() #245
可以看到,时间从30508.997167ms降低到了377.296708ms。
6、总结
呼吁各位小伙伴,编码中切记不要出现n+1次查询问题,这种问题正式上线后随着数据量的增加,注定要返工的。
Q.E.D.
相关文章
- 利用Aliddns进行端口映射,外网可以使用域名访问,在公司内网用域名访问不通。
- 使用 PyTorch 进行音频信号处理的数据操作和转换
- 使用WebSocket在Server类中无法使用Autowired注解进行自动注入
- [JCIM | 论文简读] 使用强化学习和基于图的深度生成模型进行从头合成药物设计
- TrueNAS使用笔记:创建WebDAV文件共享
- 使用PyTorch-LSTM进行单变量时间序列预测的示例教程
- 【Groovy】MOP 元对象协议与元编程 ( 方法注入 | 使用 MetaClass 进行方法注入普通方法 )
- 【Groovy】编译时元编程 ( 编译时方法注入 | 使用 buildFromSpec、buildFromString、buildFromCode 进行方法注入 )
- SQLServer 错误 17142 SQL Server 服务已经暂停。 不允许进行新的连接。 要恢复此服务,请使用 SQL 计算机管理器或控制面板中的服务应用程序。 故障 处理 修复 支持远程
- 使用NIO进行文件拷贝详解编程语言
- Oracle 视图 DBA_HIER_COLUMNS 官方解释,作用,如何使用详细说明
- 使用Linux BG命令追求高效完成任务(linuxbg命令)
- 使用PHP和MySQL实现统计分析的可能性(phpmysql统计)
- 使用Jira在Linux上进行项目管理(jiralinux)
- 使用Oracle JDBC连接实现多种数据库功能(oraclejdbc连接)
- 策略【Java】使用Redis进行过期策略管理(redisjava过期)
- 使用 AppImage 进行 Linux 软件包管理
- Linux如何使用中文URL进行网页访问?(linux中文url)
- 使用MongoDB进行强力数据库培训视频(mongodb培训视频)
- MySQL优化:使用EF进行高效管理(efformysql)
- 研究如何使用VB编程连接MS SQL Server 2008(vb mssql2008)
- 使用MSSQL工具获取汉字全拼(mssql 获取全拼)
- 使用Oracle批量删除记录的简便之道(oracle批量删除)
- MySQL中值的操作与使用方法详解(mysql中值)
- 使用CMD操作Mysql数据库(cmd和mysql数据库)
- 使用Redis建立数据表,提升存储效率(用redis建表)
- 使用K8s部署Oracle,裁剪应用复杂性(k8s 部署oracle)
- MySQL无法使用IP地址进行连接(mysql不支持ip链接)
- MySQL无法使用循环语句处理(mysql不提供循环语句)
- 使用Oracle将全部值进行修改(oracle修改全部值)
- 使用Oracle OSW构建企业级动态IT环境(oracle osw)
- php中有关字符串的4个函数substr、strrchr、strstr、ereg介绍和使用例子
- Android中使用ViewFlipper进行手势切换实例
- java中使用数组进行模拟加密的方法
- MySQL中使用innobackupex、xtrabackup进行大数据的备份和还原教程