使用Lightrun对Java应用程序进行性能调整

简介: 简介在这篇文章中,我将向你展示使用Lightrun分析一个Java应用程序,这样你就可以发现各种性能调整的改进,你可以应用到你当前的Java应用程序。在上一篇文章中,我解释了什么是Lightrun,以及你如何使用它来注入动态日志、捕获运行时快照或添加动态指标。在这篇文章中,我将使用Lightrun作为我的JPA关联获取验证器的替代品。

简介

在这篇文章中,我将向你展示使用Lightrun分析一个Java应用程序,这样你就可以发现各种性能调整的改进,你可以应用到你当前的Java应用程序。

在上一篇文章中,我解释了什么是Lightrun,以及你如何使用它来注入动态日志、捕获运行时快照或添加动态指标。

在这篇文章中,我将使用Lightrun作为我的JPA关联获取验证器的替代品。

DefaultLoadEventListener

当使用Hibernate获取JPA实体时,会触发一个 LoadEvent ,由 DefaultLoadEventListener ,处理方式如下。

网络异常,图片无法展示
|

DefaultLoadEventListener 将检查该实体是否位于当前JPA持久化上下文或第一级缓存中。如果在那里找到了实体,那么就会返回相同的对象引用。

这意味着,两个连续的实体获取调用将总是返回相同的Java Object 引用。这就是JPA和Hibernate提供应用级可重复读取的原因。

如果在第一级缓存中没有找到实体,Hibernate将尝试从第二级缓存中加载它,如果且仅当第二级缓存被启用。

最后,如果实体不能从任何缓存中加载,它将被从数据库中加载。

现在,这个过程可以在调用 EntityManager.find ,在遍历一个关联时发生,也可以间接地用于 FetchType.EAGER 策略。

检查N+1查询问题

JPA关联获取验证器文章解释了如何以编程方式断言JPA关联获取。这个工具在测试过程中非常有用,但是对于那些要第一次检查生产系统的顾问来说就不太实用了。

例如,让我们举一个 Spring PetClinic 应用程序的例子。

@Entity
@Table(name = "pets")
public class Pet extends NamedEntity {
    @Column(name = "birth_date")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate birthDate;
    @ManyToOne
    @JoinColumn(name = "type_id")
    private PetType type;
    @ManyToOne
    @JoinColumn(name = "owner_id")
    private Owner owner;
}
复制代码

Pet 实体有两个父关联, typeowner ,每个都被注解为 @ManyToOne 。然而,默认情况下, @ManyToOne 关联使用 FetchType.EAGER 的获取策略。

因此,如果我们加载2个 Pet 实体,同时也获取它们相关的 owner 关联。

List<Pet> pets = entityManager.createQuery("""
    select p
    from Pet p
    join fetch p.owner
    where p.id in :petIds
    """)
.setParameter("petIds", List.of(3L, 6L))
.getResultList();
复制代码

Hibernate将执行3次查询。

SELECT 
    p.id as id1_1_1_,
    p.name as name2_1_1_, 
    p.birth_date as birth_da3_1_1_, 
    p.owner_id as owner_id4_1_1_, 
    p.type_id as type_id5_1_1_, 
    o.id as id1_0_0_, 
    o.first_name as first_na2_0_0_, 
    o.last_name as last_nam3_0_0_, 
    o.address as address4_0_0_, 
    o.city as city5_0_0_, 
    o.telephone as telephon6_0_0_
FROM 
    pets p 
JOIN 
    owners o ON o.id = p.owner_id 
WHERE 
    p.id IN (3, 6)
SELECT 
    pt.id as id1_3_0_, 
    pt.name as name2_3_0_ 
FROM 
    types pt 
WHERE 
    pt.id = 3
SELECT 
    pt.id as id1_3_0_, 
    pt.name as name2_3_0_ 
FROM 
    types pt 
WHERE 
    pt.id = 6
复制代码

那么,为什么会有3个查询被执行,而不是只有一个?这就是臭名昭著的N+1查询问题。

使用Lightrun进行Java性能调优

虽然你可以使用集成测试来检测N+1查询问题,但有时你不能这样做,因为你被雇来分析的系统已经部署到生产中,而你还没有看到源代码。

在这种情况下,像Lightrun这样的工具就变得非常方便,因为你可以简单地动态注入一个运行时快照,这个快照只有在满足特定条件时才会被记录。

第一步是在 DefaultLoadEventListener Hibernate类的 loadFromDatasource 方法中添加一个运行时快照。

网络异常,图片无法展示
|

注意,快照只记录相关的 LoadEventisAssociationFetch() 方法返回 true 。这个条件允许我们捕获N+1查询问题所执行的二次查询。

现在,当加载所有姓戴维斯的宠物主人时,PetClinic应用程序会执行以下SQL查询。

SELECT DISTINCT 
    o.id AS id1_0_0_,
    p.id AS id1_1_1_,
    o.first_name AS first_na2_0_0_,
    o.last_name AS last_nam3_0_0_,
    o.address AS address4_0_0_,
    o.city AS city5_0_0_,
    o.telephone AS telephon6_0_0_,
    p.name AS name2_1_1_,
    p.birth_date AS birth_da3_1_1_,
    p.owner_id AS owner_id4_1_1_,
    p.type_id AS type_id5_1_1_,
    p.owner_id AS owner_id4_1_0__,
    p.id AS id1_1_0__
FROM 
    owners o
LEFT OUTER JOIN 
    pets p ON o.id=p.owner_id
WHERE 
    o.last_name LIKE 'Davis%'
SELECT 
    pt.id as id1_3_0_, 
    pt.name as name2_3_0_ 
FROM 
    types pt 
WHERE 
    pt.id = 6
SELECT 
    pt.id as id1_3_0_, 
    pt.name as name2_3_0_ 
FROM 
    types pt 
WHERE 
    pt.id = 3
复制代码

而在检查Lightrun快照控制台时,我们可以看到有两条记录被注册。

第一个快照看起来如下。

网络异常,图片无法展示
|

而第二个快照看起来是这样的。

网络异常,图片无法展示
|

请注意,由于大量使用了 FetchType.EAGER 策略,这两个快照对应于Spring Petclinic应用程序执行的二级查询。

很酷,对吗?

结论

虽然你可以在测试过程中使用JPA关联获取验证器来检测这些N+1查询问题,但如果你的任务是分析一个你从未见过的运行时系统,那么Lightrun就是一个发现各种问题及其发生原因的伟大工具。

特别是因为Java性能调优是我被雇用的最常见的原因之一,Lightrun是我的工具集的一个很好的补充。


相关文章
|
18天前
|
机器学习/深度学习 Java 编译器
解锁硬件潜能:Java向量化计算,性能飙升W倍!
编译优化中的机器相关优化主要包括指令选择、寄存器分配、窥孔优化等,发生在编译后端,需考虑目标平台的指令集、寄存器、SIMD支持等硬件特性。向量化计算利用SIMD技术,实现数据级并行,大幅提升性能,尤其适用于图像处理、机器学习等领域。Java通过自动向量化和显式向量API(JDK 22标准)支持该技术。
50 4
|
26天前
|
存储 数据采集 搜索推荐
Java 大视界 -- Java 大数据在智慧文旅旅游景区游客情感分析与服务改进中的应用实践(226)
本篇文章探讨了 Java 大数据在智慧文旅景区中的创新应用,重点分析了如何通过数据采集、情感分析与可视化等技术,挖掘游客情感需求,进而优化景区服务。文章结合实际案例,展示了 Java 在数据处理与智能推荐等方面的强大能力,为文旅行业的智慧化升级提供了可行路径。
Java 大视界 -- Java 大数据在智慧文旅旅游景区游客情感分析与服务改进中的应用实践(226)
|
27天前
|
机器学习/深度学习 数据采集 数据可视化
Java 大视界 -- 基于 Java 的大数据可视化在城市空气质量监测与污染溯源中的应用(216)
本文探讨Java大数据可视化在城市空气质量监测与污染溯源中的创新应用,结合多源数据采集、实时分析与GIS技术,助力环保决策,提升城市空气质量管理水平。
Java 大视界 -- 基于 Java 的大数据可视化在城市空气质量监测与污染溯源中的应用(216)
|
26天前
|
存储 监控 数据可视化
Java 大视界 -- 基于 Java 的大数据可视化在企业生产运营监控与决策支持中的应用(228)
本文探讨了基于 Java 的大数据可视化技术在企业生产运营监控与决策支持中的关键应用。面对数据爆炸、信息孤岛和实时性不足等挑战,Java 通过高效数据采集、清洗与可视化引擎,助力企业构建实时监控与智能决策系统,显著提升运营效率与竞争力。
|
26天前
|
Java 大数据 数据处理
Java 大视界 -- 基于 Java 的大数据实时数据处理在工业互联网设备协同制造中的应用与挑战(222)
本文探讨了基于 Java 的大数据实时数据处理在工业互联网设备协同制造中的应用与挑战。文章分析了传统制造模式的局限性,介绍了工业互联网带来的机遇,并结合实际案例展示了 Java 在多源数据采集、实时处理及设备协同优化中的关键技术应用。同时,也深入讨论了数据安全、技术架构等挑战及应对策略。
|
26天前
|
数据采集 搜索推荐 Java
Java 大视界 -- Java 大数据在智能教育虚拟学习环境构建与用户体验优化中的应用(221)
本文探讨 Java 大数据在智能教育虚拟学习环境中的应用,涵盖多源数据采集、个性化推荐、实时互动优化等核心技术,结合实际案例分析其在提升学习体验与教学质量中的成效,并展望未来发展方向与技术挑战。
|
1月前
|
Cloud Native 前端开发 Java
WebAssembly 与 Java 结合的跨语言协作方案及性能提升策略研究
本文深入探讨了WebAssembly与Java的结合方式,介绍了编译Java为Wasm模块、在Java中运行Wasm、云原生集成等技术方案,并通过金融分析系统的应用实例展示了其高性能、低延迟、跨平台等优势。结合TeaVM、JWebAssembly、GraalVM、Wasmer Java等工具,帮助开发者提升应用性能与开发效率,适用于Web前端、服务器端及边缘计算等场景。
62 0
|
26天前
|
机器学习/深度学习 人工智能 自然语言处理
Java 大视界 -- Java 大数据机器学习模型在自然语言生成中的可控性研究与应用(229)
本文深入探讨Java大数据与机器学习在自然语言生成(NLG)中的可控性研究,分析当前生成模型面临的“失控”挑战,如数据噪声、标注偏差及黑盒模型信任问题,提出Java技术在数据清洗、异构框架融合与生态工具链中的关键作用。通过条件注入、强化学习与模型融合等策略,实现文本生成的精准控制,并结合网易新闻与蚂蚁集团的实战案例,展示Java在提升生成效率与合规性方面的卓越能力,为金融、法律等强监管领域提供技术参考。
|
26天前
|
存储 人工智能 算法
Java 大视界 -- Java 大数据在智能医疗影像数据压缩与传输优化中的技术应用(227)
本文探讨 Java 大数据在智能医疗影像压缩与传输中的关键技术应用,分析其如何解决医疗影像数据存储、传输与压缩三大难题,并结合实际案例展示技术落地效果。
|
26天前
|
机器学习/深度学习 安全 Java
Java 大视界 -- Java 大数据在智能金融反洗钱监测与交易异常分析中的应用(224)
本文探讨 Java 大数据在智能金融反洗钱监测与交易异常分析中的应用,介绍其在数据处理、机器学习建模、实战案例及安全隐私等方面的技术方案与挑战,展现 Java 在金融风控中的强大能力。

热门文章

最新文章