第八章--第三节:性能优化的代码调优

第八章:软件构造的性能

第三节:性能优化的代码调优


问题一:代码调优的策略和过程

    代码调优:代码调优不是为了修复bug,而是对正确的代码进行修改以提高其性能。

  • 调优不会减少代码行数
  • 不要猜原因,而应有明确的优化目标
  • 不要边写程序边调优
  • 不是性能优化的第一选择
  • 代码行数与性能之间无必然的联系
  • 代码调优建立在对程序性能的精确度量基础之上(profiling)

问题二:代码调优的模式

    1.单例模式(Singleton Pattern)

    含义:某些类在应用运行期间只需要一个实例。

    理解:程序员一般需要对象时就new,导致创建多个object。强制client只能创建一个object实例,避免因为new操作所带来的时空性能(尤其是GC)的损失,也便于复用。

    方法:

  •     设置静态变量来存储单一实例对象
  •     将构造器设置为private,从而client无法new
  •     提供静态方法来获取单一实例对象
  •     进一步提升性能:在需要的时候再new,而非提前构造出来第八章--第三节:性能优化的代码调优

    2.轻量模式(Flyweight Pattern)

    问题特征:考虑文本编辑器中的“字符”,同一个字符重复出现多次,代表同样内容,但字体字号等不同。

    含义:该模式允许在应用中不同部分共享使用objects,降低大量objects带来的时空代价。

    对象的内部状态:不管在什么场合使用该object,内部特征都不变。

    对象的外部状态:不是固定的,需要在不同场合context分别指派/计算其值。

    例:游戏中的玩偶,有很多个,每个玩偶具有某些固有属性(Shape),但玩偶在不同的场景下颜色不同(Color)。

    无需为每个玩偶new一个object,可以复用。↓↓↓

    第八章--第三节:性能优化的代码调优

  • 轻量模式和单例模式的对比

    单例:不区分各场合下的不同表现形式,统一用一个实例来表示

    轻量对象:同一个事物,具有多种不同的表现形式。

    (故Flyweight在object层面的复用比Singleton更灵活)

    4.原型模式(Prototype Pattern)

    含义:通过克隆而非new来创建object

    原因:直接new的时空代价高,尤其是需要与外部I/O、网络、数据库打交道时候。

    实例:

    第八章--第三节:性能优化的代码调优

  • Object.clone()是protected:它可以被同包(java.lang)下以及它(java.lang.Object)的子类访问。
  • 自定义类无法直接使用Object.clone():没有访问权限(invisible),故需要override。

引用拷贝VS对象拷贝

第八章--第三节:性能优化的代码调优

第八章--第三节:性能优化的代码调优

    ①浅拷贝:使用一个已知实例的成员变量对新创建实例的成员变量逐个赋值。

(只复制对象本身,但不复制对象对外的引用)

    ②深拷贝:类的拷贝方法不仅要复制对象的所有非引用成员变量值(简单数据类型),还要为引用类型(对象)的成员变量创建新的实例,并且初始化为原对象的值。

  • clone()新对象与原对象要相互独立,要求deep copy
  • 缺省实现是shallow copy而非deep copy!
  • 在让你的ADT支持Cloneable接口的时候,千万注意自己override的clone()正确的实现了deep copy。

    4.对象池模式(Object Pool Pattern)

    问题描述:仍然是关于new的巨大性能代价,很多时候,object不用了就直接扔掉,需要时再new一个新object。

    含义:对象复用:不要扔掉object,留着后续复用

    代价:原本可被GC的对象,现在要留在pool中,导致内存浪费——用空间换时间。

    5.规范化(Canonicalizing Objects

    含义:不要保留对象的多个拷贝,仅保留少量object即可。

  •     ==比equals()的效率更高,所以尽可能将object转化为简单数据类型加以存储和处理
  • 用int取代其他常量object
  • int比String的时空性能更高

    6.规避垃圾回收(Avoiding Garbage Collection)

    核心思想:减少创建object的数量,避免GC的代价

    例:   第八章--第三节:性能优化的代码调优

  • 尽可能使用简单数据类型,对类的成员变量也是如此。
  • 局部的简单数据类型在stack中存储,GC代价低;
  • 类的简单类型成员变量在GC的时候代价也低,若为object成员变量则需GC

    7.对象初始化(Object Initialization)

问题三:对Strings的代码调优

    字符串常量池:是堆中的一块特殊的内存区域用来存储字符串对象的引用。

  • 第八章--第三节:性能优化的代码调优,首先检查字符串常量池,若字符串存在在其中,则直接让s指向这个字符串常量;否则在池中创建一个新的字符串对象。
  • 第八章--第三节:性能优化的代码调优都创建在堆中。

**例:

第八章--第三节:性能优化的代码调优