首页
|
新闻
|
新品
|
文库
|
方案
|
视频
|
下载
|
商城
|
开发板
|
数据中心
|
座谈新版
|
培训
|
工具
|
博客
|
论坛
|
百科
|
GEC
|
活动
|
主题月
|
电子展
注册
登录
论坛
博客
搜索
帮助
导航
默认风格
uchome
discuz6
GreenM
»
MCU 单片机技术
»
PowerPC
» 使用 IBM Support Assistant 找出在企业应用程序中确定和解决性能问题的模式(1)
返回列表
回复
发帖
发新话题
发布投票
发布悬赏
发布辩论
发布活动
发布视频
发布商品
使用 IBM Support Assistant 找出在企业应用程序中确定和解决性能问题的模式(1)
发短消息
加为好友
look_w
当前离线
UID
1066743
帖子
8283
精华
0
积分
4142
阅读权限
90
在线时间
233 小时
注册时间
2017-6-23
最后登录
2019-5-18
论坛元老
UID
1066743
1
#
打印
字体大小:
t
T
look_w
发表于 2018-8-13 21:30
|
只看该作者
使用 IBM Support Assistant 找出在企业应用程序中确定和解决性能问题的模式(1)
案例研究 1:基础架构代码中的内存泄漏我们的第一个案例研究涉及一个开源基准,其名称为 。RUBiS 模拟一个拍卖网站。它配备了自己的工作负载驱动程序,并且有一个 Web 层连接到一个数据库层。在有关性能评估的研究论文中已大量引用它(参见 )。
当使用 RUBiS 作为我们进行其他研究的一个基准时,我们注意到,RUBiS 在实验结束时会停止响应,并且必须重新启动才可以进行下一个实验。我们正在使用 servlet 版本的 RUBiS 和 MySQL JDBC 驱动程序。我们使用 对 100 个客户端的恒定负载分析了该应用程序详细的 GC 日志。通过 Java 命令行或通过对大多数商用应用服务器的管理用户界面,可以很容易地启用详细的 GC 日志。结果显示,即使在恒定负载(参见图 1)的情况下,所使用的堆也始终在不断增长。这似乎是一个典型的内存泄漏问题。然而,我们发现,该内存泄漏的根本原因并没有像大部分经典的内存泄漏那么明显。
图 1. GCMV:在恒定负载的情况下,RUBiS 堆的使用量在不断增长
对于内存泄漏分析,最好先了解一些基本定义:
Shallow size
,一个对象的 Shallow 大小是指用于存储对象本身所分配的内存量,没有考虑到所引用的对象。
Retained size
,一个对象的 Retained 大小是其 Shallow 大小加上只可以从该对象直接或间接访问的对象的 Shallow 大小。
Retained set
为 X,如果 X 是被收集的垃圾,那么 Retained 集所代表的一组对象就将是被收集的垃圾。
Dominator tree
是一个转换,将循环的对象图转换成 Keep-Alive 树,树中的每个节点直接负责保持其子节点的活动状态。
我们首先使用 在几分钟内在恒定负载条件下提取此应用程序的两个堆转储,并比较它们。在大多数商用应用服务器中都可以很容易地启用堆转储。快速浏览一下在这两个堆转储中的对象计数,可以使我们注意到一组已经比原始数量和大小增长了近两倍的对象。这些对象大多是原始类型,但增长得最多的那些与 JDBC 中的 PreparedStatement(这种对象的数量在第一个和第二个堆转储之间几乎翻了一番)调用相关。图 2 显示了增长最多的对象的快速分解。在大多数内存泄漏中,有一些容器对象的大小增长最多,而另一些对象类型则是计数的增长最多。
图 2. MAT: 两个堆转储之间增长最多的 RUBiS 对象
从图 2 中的快照可以看到,PreparedStatement 类型的对象计数增长得最多。然而,我们仍然需要找到在代码中的哪个部分使此计数增加(换句话说,此内存泄漏位于代码中的哪个位置)。有一个方法可以做到这一点,在 MAT 中查看支配树(参见图 3)。您可以清楚地看到两个 servlet(ViewBidHistory 和 BrowseCategories)在所使用的堆中占了 50% 以上,这两个类很可能包含了内存泄漏的代码。
图 3. MAT: 支配树中有两个 servlet 在所使用的堆中所占比例超过 50%
因为我们手上有该应用程序的源代码,我们在两个 servlet(ViewBidHistory 和 BrowseCategories)中搜查 PreparedStatement 对象的使用,我们发现了图 4 所示的模式。还记得,一个 PreparedStatement 对象代表一个预编译的 SQL 语句,通过指定的赋值方法可以设置每次的 IN 参数。通过这种方式,它可以多次重用于高效执行 SQL 语句。然而,RUBiS 代码在一个循环内重复创建了许多 “临时的” PreparedStatement 对象,但只关闭所创建的最后一个实例。 说明,关闭 JDBC 驱动程序应该关闭与一个连接相关联的所有 PreparedStatement(此时连接已关闭)。在这种情况下,JDBC 驱动程序没有在关闭连接时关闭 PreparedStatement 对象,并保留了引用,这导致那些对象没有被作为垃圾收集,所以它们的数量不断增加,从而导致内存泄漏。
有两种方法可以修复这种泄漏:将语句关闭方法移至循环内,或将语句创建移到循环上方。两种方法都将修复内存泄漏,但后者可能会提供更好的性能。我们发现,RUBiS 中的 22 个 servlet 中有 7 个由于这种使用模式而在各个地方发生内存泄漏。图 5 显示了在修复内存泄漏后,GCMV 中所产生的恒定负载的堆使用图。请注意,所使用的堆几乎如预期般保持不变。
图 4. 内存泄漏根本原因的 RUBiS 代码
本案例研究强调了在基础架构代码中的内存泄漏场景,其中发生泄漏是因为使用不当以及错误的的驱动程序实现共同造成的。此外,根源原来是这么一回事,人们通常不认为这是泄露的常见原因。
图 5. GCMV: 修复内存泄漏后,恒定负载情况下的恒定 RUBiS 堆使用
收藏
分享
评分
回复
引用
订阅
TOP
返回列表
电商论坛
Pine A64
资料下载
方案分享
FAQ
行业应用
消费电子
便携式设备
医疗电子
汽车电子
工业控制
热门技术
智能可穿戴
3D打印
智能家居
综合设计
示波器技术
存储器
电子制造
计算机和外设
软件开发
分立器件
传感器技术
无源元件
资料共享
PCB综合技术
综合技术交流
EDA
MCU 单片机技术
ST MCU
Freescale MCU
NXP MCU
新唐 MCU
MIPS
X86
ARM
PowerPC
DSP技术
嵌入式技术
FPGA/CPLD可编程逻辑
模拟电路
数字电路
富士通半导体FRAM 铁电存储器“免费样片”使用心得
电源与功率管理
LED技术
测试测量
通信技术
3G
无线技术
微波在线
综合交流区
职场驿站
活动专区
在线座谈交流区
紧缺人才培训课程交流区
意见和建议