Java——提升软件性能

  • Post author:
  • Post category:java


在学习了软件构造课程后,我对于如何写出一个较为完善的软件有了更深入的了解,这门课程中有一部分内容讲的是性能优化有关的,在结合自身所了解的一些知识,我整理了下软件性能的提升一些方法。


一 代码阶段

我们在具体实现一个产品的时候,要对自己所写的代码有更深入的理解,并时刻反思有没有更优的方案实现功能。我们来看一段代码,如下图所示:

这段代码实现了一个简单的对list中元素求和的功能,这样简单的代码是不是已经没有优化空间了呢?实则不然。我们仔细观察for()循环这行代码,我们可以看到其中终止条件的判断是I<temp.size(),循环每进行一次,都会调用一遍size()函数,在本例中所创建的list长度较小,但在大型程序中这样的时间开销是不可以忽略的,我们只需要做一步简单的操作就可以避免这个问题。在循环外部使用length保存size()方法的值,将判断条件改为i<length。

那么这段代码是不是已经完美了呢,答案依然是否定的。我们可以对循环内部的sum加法进行优化,将原来一个sum的累计过程划分为两个子问题相加,代码如下:

通过对一系列大数据的测试我们可以清楚的看到算法性能的优化。从这个例子我们可以看出,尽管我们的代码都实现了一种操作,但是由于代码的实现不同,有时仅仅改变了一个参数的位置就造成了我们程序性能的差异。因此,在我们设计自己的程序过程中,要反复思考自己的代码是否具有更优的实现方式,例如如何避免一个函数的重复调用,选择高效算法。


二代码调优



代码调优是在程序实现后进行的一部优化过程,代码调优不是为了修复bug,而是对正确的代码进行修改以提高其性能。通常是小规模的变化。

代码调优的过程为:1.备份 2. 通过度量发现热点瓶颈 3.分析原 因,评判代码调优的必要性 4.调优 5.每次调优后都要重新度量 6.若无效果或负效果,则回滚。

接下来,我们介绍下代码调优的几种模式。

1)Singleton Pattern

单例模式。某些类在应用运行期间只需要一个实例,程序员一般需要对象时就new,导致创建多个object, 更好的选择是强制client只 能创建一个object实例,避免因为new操作所带来的时空性能(尤其是GC)的损失,也便于复用。

在上图示例中,用户可以通过getInstance()获得对象,但是只会新建一次。

2)Flyweight Pattern

轻量模式。该模式允许在应用中不同部分共享使用objects,降低大量objects带来的时空代价。例如我们需要cat这个对象,cat对象拥有肥胖和公母这两个对外展示的属性,同时还有一个属性为品种,但是这个属性是固定的。我们需要cat对象在不同场景的应用中展现不同的肥胖和公母属性。

3)  Prototype Pattern

原型模式。通过克隆而非new来创建object, 直接new的时空代价高,尤其是需要与外部I/O、网络、数据库打交道时候。例如ConcreteGraph。

4)  Object Pool Pattern

对象池模式。很多时候,object不用了就直接扔掉,需要时再new一个新object, 对象复用:不要扔掉object,留着后续复用。原本可被GC的对象,现在要留在pool中,导致内存浪费—— 用空间换时间。


三 GC调优

在程序运行中,要尽可能减少GC时间,一般不超过程序 执行时间的5%, 在启动程序时,可为其配置内存分配的具体大小。堆的大小决定着VM将会以何种频度进行 GC、每次GC的时间多长这两个指标具体取值多少为“优”,需要针对特定应 用进行分析, 较大的heap会导致较少发生GC,但每次GC时间很长。 如果根据程序需要 来设置heap大小,则需要频繁GC,但每次GC的时间较短。

配置JVM参数并获得最优参数示例:

如何找到并配置参数需要程序员对自己的程序进行分析后然后进行调试,这是个比较复杂的过程而且最后的收益也可能不如预期,在程序没有其他地方可以优化的时候再使用这个策略进行调优。




总结



提升程序性能还有很多方法


,例如我们还可以借助第三方工具(例如

Visual VM

)发现热点方法,对热点方法进行优化,分析memory dump找到程序中存在的一些问题。总而言之,只有通过大量的实践和积累我们才能掌握更多方法,从而写出性能更佳的程序。




版权声明:本文为yuyu_1998原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。