`

关注性能: 边缘剖析(工具太胖怎么办?)

阅读更多

    调优的并不总是速度,有时候需要调整应用程序的其他方面,如果应用程序需要调优,要做的第一件事通常是使用剖析程序监控应用程序。但是,剖析并不总是可行的,有时候原因可能很可笑。 关注性能的本期文章中, Jack 和 Kirk 讲述了他们最近经历的一件事:他们奉命剖析一个胖客户机,事实上它是如此庞大,根本没有为剖析程序留下空间。

我们从来还没有遇到过调优应用程序内存占用的问题。通常,我们看到的和内存有关的调优要求都涉及到降低垃圾收集的开销,理想情况下可以通过调整堆的大小或者改变垃圾收集算法来解决,如果不行的话,还可以采用各种技术减少内存中的对象。但是,有时候无论分配和垃圾收集的效率如何,应用程序都要占用很多的内存。

减肥中心之旅

最近,我们奉命降低一个胖客户机的内存占用。虽然“胖客户机”一词通常表示普通的 GUI 客户应用程序,而这个客户机却是几近肥胖症。这个客户机在 Windows 平台上运行,处理大小的极限是 2 GB。去掉可执行地址空间和引入各种 JNI 产品所需要的其他空间之后,该应用程序能够使用的最大堆大小大约是 1.2 GB 或者 1.3 GB。不幸的是,某些用户因为要向该应用程序灌输大量的数据,以至于占用的空间常常接近这个极限。最明显的调优方案是转移到 Unix 机器上,但是因为不切实际而被排除掉了——客户更愿意让这个应用程序减肥。

于是,我们的任务就定下来了。对这个胖客户机进行剖析,看看到底是什么占用了这些空间。然后对这些对象减肥,为以后的扩展或者更大的数据量留下空间。我们认为这事很容易。可能要花点时间,因为减少对象的数量通常不能一蹴而就,但是这么大的堆, 肯定有很多赘肉能够割掉。我们这样想。

通常的过程

我们开始了通常的内存占用缩减过程:建立测试环境、规定可再现的测试、启动剖析程序、运行测试、分析数据、查找调优的机会。时间不断流逝,我们一直忙个不停……或者说我们是这样认为的。现在,我们进入了“运行测试”阶段,剖析程序趴下了。于是我们再次尝试。又死掉了。我们改变了剖析程序的配置,将开销减到最少,再次尝试。又死掉了。根本就没留下足够容纳剖析程序完全运行的 JVM 堆空间,更不用说生成任何有用的剖析数据了。而我们使用的是一种上等的商业剖析程序,一般是很可靠的,所以我们很吃惊。

试一次,再试一次

没关系,海里有数不清的鱼,现在也有数不清的剖析程序(关于剖析程序的最新评述,请参阅 Resources)。又是一天,又使用了一个剖析程序,怎么样呢?不幸的是,测试过程是惊人的相似。和一号剖析程序差不多在同一点上,二号剖析程序又让 JVM 崩溃了。和一号剖析程序一样,它甚至可以做更多的配置,重新配置,降低开销,去掉更多的数据。但它还是和一号剖析程序一样,也崩溃了。糟糕的是,三号剖析程序也没有什么不同。

巧妙的剖析程序

但是,四号剖析程序有了微妙的变化。对存活对象的快照进行内存分析(忽略对象的创建和垃圾收集,只观察某一点上存活对象的快照),在请求进行快照之前,四号剖析程序根本没有增加 JVM 的开销。成功了!我们的测试第一次在剖析程序运行的时候通过了需要拍摄快照的那个点。我们很高兴。然后我们激活了快照,于是 JVM 崩溃了。

我们又尝试了一次,但是这个剖析程序生成快照需要太多的额外空间。根本无法工作。我们又回到了起点!尽管还有半打商业剖析程序可供尝试,但结果是显然的。应该做一些横向思考了。

具有讽刺意味的是,我们的问题正在于剖析程序本身的复杂性。我们需要某种简单的东西。当然,简单并不意味着开销低,但是既然那些复杂的剖析程序令我们失望,不妨试一试。于是我们开始扫描开放源代码剖析程序。

重新开始

我们首先寻找那些看来是用于内存分析的剖析程序。一号开发源代码内存剖析程序看起来绝对简单,也许过于简单了。输出结果用处不大,只有一个类列表和每个类的对象个数。但无论如何这也算是一个不错的起点。它崩溃了。我们陷入了重走老路的担忧。二号开放源代码剖析程序甚至比一号还简单,虽然它实际上给出了更详细的信息:每个对象都有堆占转储记录,说明对象的大小和所属的类。和其他剖析程序一样,我们用较低的配置尝试,于是可以看到堆转储逐渐增大——大致就是堆的大小,然后,我们看到的是一个 1 GB 的输出文件。我们尝试了它,它击溃了虚拟机。但它确实让我们看到了部分堆转储。

在处理像这种很大的因素时,必须能够判断所需资源的数量级和要花费的时间。转存 1 GB 的文件可能要花很多时间。如果没有考虑到一个操作可能花费多长的时间,您可能错误地认为进程被挂起了,而实际上它仍然在运行,只是要花费转储 1 GB 格式化文本所需要的时间。这个开放源代码剖析程序正在工作,但是第一次测试时我们忽视了给它足够的时间。更遭的是,第一次还没有结束的时候,我们又迫使它进行第二次转储,结果造成了崩溃。所幸的是,我们认识到问题在我们自己而不是剖析程序,有了较多的认识之后,我们再次进行了尝试并取得了成功。

heapprofile 剖析程序

那么,到底哪个剖析程序成功了呢?它就是 Matthias Ernst 编写的“heapprofile”。它仅用了一页 C 代码,使用 Java Virtual Machine Profiler Interface (JVMPI) 把堆转存成最简单的格式。甚至还要自己编译,网站上(请参阅 Resources)没有提供预编译的可执行文件。这种简单性正是我们在这个问题里所需要的。没有任何开销。除了绝对必要的之外,没有使用堆或者 JNI 资源。程序运行的时候它什么也不做,当我需要堆转储的时候,它仅仅遍历一次堆,直接将每个对象的大小和类转存到一个文件,没有在内存中创建任何结构,正是这种结构让其他所有剖析程序击溃了 JVM。

当然,事情还没有完。现在我们需要分析结果数据,使用它确定应用程序所用的对象。幸运的是,输出格式很容易解析。一旦找到了造成问题的对象,我们还需要找到分配这些对象的地方。为了降低开销,我们采用重新编译这几个类的简单策略,在构造函数中放上栈跟踪程序,Jack 的著作(请参阅 Resources)中详细描述了这种技术。这种简单的技术需要在构造函数中创建(而不是抛出)异常。异常中包含分配地点的栈踪迹。然后可以将所有对象的这些栈列成表格。因为多数栈都是相同的,标识调用栈以及链接到每个栈的相关实例个数需要存储的数据并不很多(最多几千个字符串)。

简单而丑陋

这都是些简单的技术,但并没有很高的生产率。我们更愿意使用功能完备的剖析程序输出数据,尤其是因为它们提供的数据更便于分析。我们本来希望从堆的根开始,向下跟踪较大的节,直到发现大量引用堆的对象,但是我们没有选择这个方法。

和通常使用调优技术相比,这次使用的技术比较简陋。但最终我们发现了一些完全不需要的对象,使用一些类的不同实现可以完全消除它们;另一些必需的对象也可以苗条一点,或者压缩到一起,减少其空间需求。对象缩减通常都是如此,胖客户机减肥也没有一定之规。和人类一样,让 Java 应用程序节食也是很困难的事情。也和节食一样,去掉身上多余的脂肪往往比您所想的要花费更长时间。令人遗憾的是,虽然我们从这个胖客户机上刮掉了两百兆字节,但它仍然没有瘦到足以容纳“真正的”内存剖析程序的运行。

结束语

我们曾经在 Unix 讨论组看到这样一个问题 —— “Unix 大师们使用什么编辑文本?”,随后的讨论纷纷开始鼓吹 vi、Emacs 等。但毫无疑问,正确的答案应该是“Unix 大师使用任何能用的工具编辑文本。” Java 平台拥有一些非常杰出的剖析程序。但最终,调优应用程序必须分析数据,无论用何种方法,您必须拿到这些数据。

 

 

 

 

 

 

 

转自http://www.ibm.com/developerworks/cn/java/j-perf09024.html

分享到:
评论

相关推荐

    一种改进的医学图像边缘检测算法

    医学图像边缘检测是医学图像处理领域的核心技术之一,寻求既能精确定位图像边缘,又能 有效抑制图像噪声的算法一直都是医学图像处理领域的热点和难点。结合小波分析理论,在经典边缘检测 算法的基础上提出了一种改进...

    具有混合连续和离散边缘的规范藤蔓树的Matlab工具箱.zip

    matlab算法,工具源码,适合毕业设计、课程设计作业,所有源码均经过严格测试,可以直接运行,可以放心下载...这些工具可以帮助开发者利用多核处理器和图形处理器(GPU)来加速算法的计算过程,提高算法的性能和效率

    链接管理工具:一个链接管理工具,用于现代营销团队创建、共享和跟踪短链接

    一个链接管理工具,用于现代营销团队创建、共享和...它集成了Vercel边缘函数、Upstash Redis和PlanetScale MySQL等技术,提供了一个功能丰富的平台,帮助营销团队轻松创建和管理短链接,并跟踪链接的性能和分析数据。

    NVIDIA GTC CHINA 2020大会资料汇总(144份).zip

    HPC 应用性能分析和调优; RDMA 在分布式存储中的应用; 深度学习平台及应用: 用 NVIDIA Jarvis 来构建你的语音助理; 安全 AI 平台 GPU 实践和思考; 飞桨推理引擎性能优化; 高阶信息如何加速神经网络训练?; ...

    cpp-NetworKit是一个用于大规模网络分析的开源工具包

    NetworKit是一个用于高性能网络分析的开源工具套件。 其目的是提供分析数千到数十亿边缘大型网络的工具。 为此,它实现了有效的图算法,其中许多并行使用多核架构。

    FlashX:FlashX是大数据分析工具的集合,这些工具以图形和矩阵的形式执行数据分析

    此存储库包含FlashX项目的核心,该项目提供大数据分析工具,这些工具可以以图形和矩阵的形式执行数据分析。 这样,FlashX涵盖了广泛的数据分析任务。 FlashX中的所有工具都利用固态驱动器(SSD)将数据分析扩展到一...

    NetworKit是一个用于大型网络分析的增长型开源工具箱。-C/C++开发

    NetworKit是用于高性能网络分析的开源工具套件。 其目的是提供分析范围从数千到数十亿个边缘的大型网络的工具。 为此,它实现了ef NetworKit,这是一个用于高性能网络分析的开源工具套件。 其目的是提供分析范围从数...

    networkit:NetworKit是一个用于大型网络分析的增长中的开源工具包

    它的目的是提供分析范围从数千到数十亿个边缘的大型网络的工具。 为此,它实现了有效的图形算法,其中许多并行使用多核体系结构。 这些是为了计算网络分析的标准度量。 NetworKit专注于可扩展性和全面性。 NetworK...

    《MATLAB R2016a智能计算25个案例分析》源码

    第12章基于小波分析的图像多尺度边缘检测算法研究 12.1多尺度边缘检测 12.2快速多尺度边缘检测算法 12.3实验结果与分析 第13章基于小波的信号阈值去噪算法研究 13.1阈值去噪方法 13.2阈值风险 13.3实验结果与...

    来了解一下质量管理工具——质量屋(HOQ)

    本文来自于个人微博,HOQ是项目管理十大知识领域领域中质量管理工具中的一种,今天我们就来了解一下,什么是质量屋?质量屋(TheHouseOfQuality),又名HOQ,它是质量功能配置(QFD)的核心。一般QFD的学习会涉及到。...

    MATLAB的数据采集与分析系统源代码

    而LabVIEW刚好是标准的数据采集和仪器控制软件,以其强大的数据采集、数据分析和仪器控制功能在现代测控领域中得到了广泛的应用,但在数值处理分析和算法工具等方面效率低,功能简单,不能满足工程上多方面的要求。...

    基于Opencv的车道线检测.zip

    3.Cany边缘检 OpenCV(Open Source Computer Vision Library)是一款开源的计算机视觉库,专门为图像和视频处理任务设计,广泛应用于学术研究、工业应用以及个人项目中。以下是关于OpenCV的详细介绍: 历史与发展 ...

    基于opencv和MFC的图像处理软件.zip

    图像的灰度化、二值化、滤波、边缘检测、直方图,视频的边缘检测和跟踪 OpenCV(Open Source Computer Vision Library)是一款开源的计算机视觉库,专门为图像和视频处理任务设计,广泛应用于学术研究、工业应用...

    4G、5G面试题.docx

    4G面试试题 1. LTE小区选择遵循什么原则 PLMN选择,根据S准则,满足S准则就可以被选择为驻留小区 ...覆盖边缘化:TTI Bunding,ROHC,边缘用户主动调度 10. 丢包分析手段 终端日志 Cell日志 FMA工具

    【重磅】史上最全的阿里云分享的云原生技术学习资料合集(120份).zip

    Edge Kubernetes - 构建边缘云计算基础设施 Improving Resource Efficiency in Kubernetes Clusters Kata Containers 云原生服务的一块坚定基石 OpenKruise — 助力阿里巴巴集团落地 Kubernetes的核心开源技术 ...

    elchemy:使用静态类型的类似于Elm的语法编写Elixir代码(与Elm工具兼容)

    快速安装 npm install -g elchemy 它是什么? Elchemy可让您编写简单,快速且高质量的... 美观且完全可读的输出-生成的代码是惯用语,高性能,并且可以轻松读取和分析,而无需查看原始源代码。 项目的成熟度 解析器

    创科机器视觉软件试用版(免费)

    CkVision集成BLOB分析,对象计数、几何匹配、灰度匹配、彩色匹配、字符识别、条码识别、测圆、找圆、卡尺测量、外径内径测量、颜色识别、图像基本运算(二值化、比例变换、开运算、闭运算、膨胀、腐蚀、滤波、边缘...

    stackprofiler:Ruby采样探查器的Web UI

    不幸的是,以我的经验,在对已经很慢的代码进行性能分析时,RubyProf的开销非常高,这使性能非常令人沮丧,即使不是没有用的。 也许我错了,但是stackprof似乎更有用。 Stackprofiler处于非常难以置信的早期开发...

Global site tag (gtag.js) - Google Analytics