知识大全 两种方法定位Java应用程序瓶颈(2)

Posted

篇首语:初心不与年俱老,奋斗永似少年时。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 两种方法定位Java应用程序瓶颈(2)相关的知识,希望对你有一定的参考价值。

两种方法定位Java应用程序瓶颈(2)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  继续最优化代码  在上面的剖析输出中 最顶端的项起源于GUI事件循环 一旦我们使GUI对象可见(即调用setVisible(true)) 事件循环就开始了 这个循环将持续应用的整个生命周期 而且可以注意到在每一文件读取之后应用就会刷新图形 这一点在文件数目较大时更为重要 假设我们并不想查看中间的图形(就是说 这并不是一个公司的需求) 通过将图形显示移动到main()的末尾 我们就可以加快应用的速度 那么 事件循环直到应用的最后一刻才会启动 paint()也将很可能只需要被调用两次   关于这一点 我们可能会产生这样的疑问 图形显示是否需要?它是否需要与应用同时显示?根据所做的回答 我们或许会将图形移动到另一线程 另一应用甚至另一机器 为了便于讨论 我们假设需要即时的图形显示   修改后的main()如下:    public static void main (String[] argv)    throws IOException    Letters letters = new Letters();   long startTime = System currentTimeMillis();      for (int i= ; i  修改后进行测试 产生如下结果   ● 平台 A: 时间在 和 秒之间   ● 平台B: 时间在 和 秒之间   我们已经大大改善了性能 但仍然没有达到我们的性能目标   附加的剖析显示   CPU SAMPLES BEGIN (total = ) Sun Jul : :   rank self accum count trace method   % % java io FileInputStream readBytes   % % sun awt windows WToolkit init   % % sun awt windows WToolkit eventLoop  这和我们前面所看到的明显不同 我们花费的时间主要集中在readBytes()上 对readBytes()我们该怎么办呢?   JDK 引入了java nio 包中一整套新类和它用于缓冲区I/O (输入/输出)的子包 有一个类 MappedByteBuffer看起来特别有用 我们可以使用MappedByteBuffer 对象在内存中高效表征一个文件的内容 这个类对缓冲区和内存管理的详细信息进行操作   为了把MappedByteBuffer对象连接到文件 我们将使用FileChannel对象 FileChannel 表征缓冲区与可进行读 写 映射和处理文件的文件之间一个可靠的线程连接 FileChannel对象保留文件当前位置信息并提供低级特定操作系统的最优化 JDK 文档包含了如何使用FileChannel和MappedByteBuffer的例子   使用 FileChannel 和 MappedByteBuffer修改代码      import java nio MappedByteBuffer;  import java nio channels FileChannel;      void countCharacters (String filename)    throws IOException    FileInputStream fis = new FileInputStream(filename);   FileChannel fc = fis getChannel();  // Get the file s size and then map it into memory   int sz = (int)fc size();   MappedByteBuffer bb = fc map(FileChannel MapMode READ_ONLY sz);     for (int i= ; i= ) && (pos <= 25))    ++countArray[pos];         fc.close();     ...  修改后产生如下结果:   ● 平台 A: 时间在2.1 和 4.7 秒之间   ● 平台B: 时间在11 和13.8 秒之间   这个结果较前一例子有了一些改善。tW.winGWIT.然而,从统计或者可感知角度来说,这可能并不重要。   好了,另一个问题:我们应该如何达到我们的性能目标呢?这些文档能不能在10秒左右的时间内处理完毕?我们已经离这一目标很近了。我们将再尝试进行另一最优化。  我们来看一下 FileChannel.map()文档,描述的底端附近有一引人注意的引用。   对多数操作系统而言,将一文件映射到内存中比通过常用的读写方法来读写好多字节数据代价更高。从性能角度来说,将相对较大的文件映射到内存中才是值得的。   ByteBuffer 类,是MappedByteBuffer\'s 超类, 提供了java.nio 包中的可缓冲输入。我们试着使用ByteBuffer而不是MappedByteBuffer 来读取数据看看会发生什么事情。   ByteBuffer类的两种方法可以获得ByteBuffer: 方法allocate(int)和 allocateDirect(int)。这两种方法的关键就是缓冲区的大小。 allocateDirect() 产生一个以字节为单位的直接型缓冲区,它能尽可能的执行本地文件的I/O。 allocate()产生一个以字节为单位的非直接型缓冲区,它交换少量的本地代码用于具有决定性的行为(很可能会慢一些)。Sun推荐将以字节为单位的直接型缓冲区用于与大型文件相关并具有较长生命周期的缓冲区。   我们修改后的代码使用以字节为单位的直接型缓冲区:   ...import java.nio.ByteBuffer;  ...   void countCharacters (String filename)    throws IOException    FileInputStream fis = new FileInputStream(filename);   FileChannel fc = fis.getChannel();  // Get the file\'s size and then map it into memory   int sz = (int)fc.size();   int bufferSize = 1024;   ByteBuffer bb = ByteBuffer.allocateDirect (bufferSize);   int nbytes = -1;   while ((nbytes = fc.read (bb)) != -1)    bb.rewind();   for (int i=0; i= 0) && (pos <= 25))    ++countArray[pos];            fc.close();     ...  这一代码运行时间结果:   ● 平台 A: 时间在2.7 和 5.2 秒之间   ● 平台B: 时间在13.1 和13.9 秒之间   使用 allocateDirect()替换allocate()将以20%的比例降低性能。性能比前一例子会少慢一些。代码也不是很容易阅读。可是,很有意思的一点,我在一个具有大约20个Java源文件的目录上使用相同的代码进行试验,结果得到了相反的结果。使用直接ByteBuffer编写的代码其速度要比使用MappedByteBuffer编写的代码快将近20%。这很可能与缓冲区和同步本地文件I/O操作所产生的附加花费有关。   所以…那一种最优化策略最好呢?这取决于应用是如何加以使用的。根据本文开始列出的需求,我将选择MappedByteBuffer版本。在我们的测试用例中它是最快的一个而且可以很好进行平衡。   重要的问题是:在我们进行最后一轮最优化测试之前,性能是否足够好了?如果已经足够好了,我们只是在花费额外时间进行并无直接好处的优化。如果性能仍然不令人满意,接下来的优化尝试很可能会更困难而且也十分耗时。   剖析如此重要的原因就是它告诉您要解决问题的信息,而且同时告诉您是否已经做到了这一点。有时候,花时间修改代码对性能并没有显著的影响。实际上或许仅仅使您的代码更难于阅读和维护。而且,您可能会对HotSpot VM 的优化策略感到意外-您不知道如何使Java程序运行的更快。   相同的改善流程对内存相关和I/O相关的性能问题一样有效。内存相关-内存漏洞和碎片帐集通常是最难追踪的。这是因为它们难于复制e而且观测程序或许会改变内存相关的行为。   改善性能的其他方法   一旦剖析确定了性能问题的位置,决定做什么仍然是需要小心处理的。这里的一些建议可用于解决特定的性能问题:   ● 方法调用:优化方法,或者尽量少调用;   ● 类读取:预先读取类,使用懒散的(命令触发)实例。注意:多线程程序中,避免使用两次检查的锁定(请参见Brian Goetz\'s "Double-Checked Locking: Clever, but Broken" (JavaWorld, February 2001)查明原因);   ● 在内存外运行: 共享对象而不是创建对象,可以使用对象工厂或者对象池;   ● 字符串处理: 使用 StringBuffer 或者 char[]而不是String;   ● 递归:消除递归方法调用并将其转换成迭代体   ● I/O 和序列: 确保I/O是使用缓冲方法的。考虑使用非同步方法编写您自己的I/O子类;   ● Collection类:使用满足应用的collection类,有时数组的访问和修改比collection更快。   性能改善的另一方法:使用字节型代码优化器。这些程序检查类文件字节代码,删除未被使用的代码,清空方法调用堆栈等。优化器最好的一点就是您不必修改任何代码-您只需测试一下看看优化器是否正常工作。令人不是很满意的地方就是优化器产生不可移植的代码或代码并未按照您所期望的方式工作。   调整程序   可感知性能比实际性能更重要。在您开始调整之前,决定如何判定什么时候性能就是足够好了。需要调整时,测试并剖析。如果它们还是有区别的,新的1.4 I/O 类可提供性能改善功能。剖析、剖析、再剖析。高效使用您的时间。不要更改代码而且在获得满意的性能之后就不必再调整。               cha138/Article/program/Java/JSP/201311/19458

相关参考

悬挂定位安装方式有哪两种?

  刚性悬挂定位安装方式有垂直和悬臂悬挂定位2种。如何选定刚性悬挂接触网的悬挂定位安装,应根据隧道净空高度和断面情况,考虑安装结构简单可靠。

悬挂定位安装方式有哪两种?

  刚性悬挂定位安装方式有垂直和悬臂悬挂定位2种。如何选定刚性悬挂接触网的悬挂定位安装,应根据隧道净空高度和断面情况,考虑安装结构简单可靠。

知识大全 本人大专计算机网路专业,发展遇到瓶颈。想学点程式设计,好就业。请问程式设计学那种语言,方便以后就业。

本人大专计算机网路专业,发展遇到瓶颈。想学点程式设计,好就业。请问程式设计学那种语言,方便以后就业。java语言是应用最广泛的,具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于PC、资料中心、

知识大全 java如何创建jar文件

  并不是所有类型的Java应用程序都能打包到单独的一个JAR文件中去必须符合一定的条件一个Java应用程序的所有文件才能打包到一个文件中去另外JAR文件有两种一种是有清单(manifest)文件的一

知识大全 怎样制作可执行的java程序

  常常在网上看到有人询问如何把java程序编译成exe文件通常回答只有两种一种是制作一个可执行的JAR文件包然后就可以像chm文档一样双击运行了而另一种是使用JET来进行  编译但是JET是要用钱买

知识大全 java内存泄漏的定位与分析

  ArrayList就是传说中的动态数组就是Array的复杂版本它提供了如下一些好处动态的增加和减少元素灵活的设置数组的大小……  认真阅读本文我相信一定会对你有帮助比如为什么ArrayList里面

知识大全 获取java线程中信息的两种方法[2]

   以上是一个多数熟悉单线程编程的人在第一反应下给出的实现方法但是该类在运行的时候输出的结果却不是期望的HelloWorld!而是Hello这是由于线程的竞争条件导致的

知识大全 tomcat中部署java项目

  在Tomcat中部署JavaWeb应用程序有两种方式静态部署和动态部署在下文中$CATALINA_HOME指的是Tomcat根目录  一静态部署  静态部署指的是我们在服务器启动之前部署我们的程序

知识大全 使用实时Java降低Java应用程序的易变性(2)

使用实时Java降低Java应用程序的易变性(2)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 

知识大全 Java进阶 Java应用程序中动态分配CPU资源[2]

Java进阶Java应用程序中动态分配CPU资源[2]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧