这里将要讲述的是一系列的类似案例,都是在各个产品进行performance tuning时被发现的,非常具有普适性。可以说在日常开发中,有非常大的概率遇到相同或者类似的情形,因此需要对其保持警惕以便避免陷入类似的性能问题。
我们从JAXBContext这个对象开始,JAXBContext 是JAXB API的入口,典型的代码实现如下:
private void unmarshal() {
JAXBContext context = JAXBContext.newInstance(DirectoryConstants.JAXB_CONTEXT_CLASS);
Unmarshaller u = context.createUnmarshaller();
Object obj = u.unmarshal(...);
}
这个是标准使用流程了,首先初始化JAXBContext对象,通过JAXBContext对象创建Unmarshaller对象,然后使用Unmarshaller对象来进行unmarshal操作。
这个写法在功能实现上没有任何问题,但是如果一旦进行压力测试,就会暴露性能问题。JAXBContext对象的初始化是个资源消耗非常大的操作,我们可以通过threaddump进行分析,会发现很多工作线程都在执行JAXBContext.newInstance()这个方法,而不是我们期待的u.unmarshal()。而事实上JAXBContext对象的Sun实现是线程安全的,即容许多线程同时调用一个JAXBContext对象的createUnmarshaller(),因此完全没有必要为每个xml的 marshaling 和 unmarshalling 操作去初始化一次JAXBContext对象。可以参考这里的说明:https://jaxb.dev.java.net/faq/index.html#threadSafety
简单点说,这个一个初始化代价昂贵,却又可重复使用的对象。
因此,我们只需要初始化JAXBContext对象一次并保存起来,然后重复使用这个JAXBContext对象即可。保存JAXBContext对象的方式可以有很多种,比如cache / threadlocal,或者使用一个单例来维持这个对象。比如下面的代码示例:
private void unmarshal() {
JAXBContext context = JAXBContextHolder.get();
...
}
public class JAXBContextHolder {
private static final JAXBContext instance = JAXBContext.newInstance(DirectoryConstants.JAXB_CONTEXT_CLASS);
public static JAXBContext get() {
return instance;
}
}
在实际项目中, 通过上面的简单改进之后,我们当时得到了一个非常巨大的回报:TPS (transactions per second 每秒事务处理量)直接*3 !!
这个案例从技术上讲非常的简单,道理很浅显,相信每个人都能轻松理解。或者说,这是一个“知道了就简单,不知道就容易犯错而不自知”的地方,因此依然有些东西需要注意:
(1) 有哪些对象有类似的特性
目前发现的类似对象有
1. 刚刚上面讲到的JAXB API中的 JAXBContext 对象
2. SOAP API中的javax.xml.soap.SOAPFactory
3. CFX client
通常情况下,在使用各种api或者工具类库时,如果发现调用代码中有类似的初始化语句,都应该稍加注意(除非明确当前代码对性能完全没有要求),可以去查一下这个类对象的javdoc或者直接看源码,如果发现满足上面所说的特性,则应该考虑进行上述的性能优化。
根据经验,类似的初始化对象通常的命名规则都是***Context/***Factory之类,或者***client,遇到类似名字时需要提高警惕。
(2)假设问题已经存在,如果才能在performance tuning中迅速发现问题的代码?
通常的办法就是用thread dump,一般连续dump个3-5次,然后通过分析thread dump信息 (推荐使用eclipse插件 lockness),看当前请求的线程(通常是一个线程池)都在干什么。一般初始化昂贵都昂贵在类似文件IO操作或者加锁之类的地方,很容易在thread dump中被发现。
分享到:
相关推荐
此外,作者还会介绍一些设计模式和最佳实践,帮助读者在实际项目中应用这些原则。 书中还会涉及测试和调试的话题,因为这些都是保证软件质量的重要环节。如何编写单元测试,如何有效地定位和修复bug,以及如何使用...
C语言接口与实现--创建可重用软件的技术.pdf
9. **软件工程实践**:除了技术细节,本书还会讨论软件开发过程中的文档编写、版本控制、代码审查等最佳实践,帮助读者提升整体的软件工程素养。 通过阅读《C语言接口与实现--创建可重用软件的技术》,开发者不仅...
在`cinterface_source`中,我们或许能找到关于动态内存分配和释放的最佳实践。 7. **可移植性**:C语言的一个优点是它的跨平台性。书中源代码可能会展示如何编写符合标准的C代码,确保在多种操作系统和硬件平台上都...
C语言接口与实现--创建可重用软件的技术.part3.rar
scalajs-react-components, 可以重用scalajs响应组件 scalajs-react-components 重用 scalajs响应实时组件。我们试图在 scala.js 中使用javascript组件的经验,通过添加类型化的包装器来尽可能。向javascript添加...
- **类与对象的设计**:如何合理划分类的职责,如何设计类的属性和方法,以及如何利用构造函数初始化对象。 - **异常处理**:在面向对象程序中,正确地捕获和处理异常是确保程序健壮性的关键。 - **测试驱动开发...
本研究在深入理解主流框架的核心思想并总结实践经验中的优缺点的基础上,结合通用框架设计理念和J2EE中更为突出的技术,从“零配置、快速开发、易于扩展”的角度出发,提出了可重用Web一站式应用架构。 该架构旨在...
Spring框架的初始化是其核心特性之一,它允许开发者在对象完全配置并准备好使用之前执行必要的初始化操作。Spring提供了两种主要的方式来实现bean的初始化:通过实现`InitializingBean`接口和使用`init-method`属性...
6. 构造函数与析构函数:构造函数用于初始化新创建的对象,而析构函数则在对象生命周期结束时执行,用于清理资源。这两个特殊方法在类的设计中起着至关重要的作用。 7. 访问控制修饰符:如public、private、...