FLASH 基于对象的优化技术 盛大游戏 黄炎中
Overview MMOG 游戏中程序的对象需求 FLASH 平台对象层面的特点 优化办法和评测 几个应用
MMOG 游戏中程序的对象需求 高对象数量要求 底层组件所需对象多 ( 图形 , 消息 , 网络 . 配置等等 ) 游戏内容庞大,需要以对象为载体实现  相同类型的对象数量也很多 对象数量增长很难预知 对象多导致内存占用量大 面向对象的编程方式决定了一切都要依赖对象
FLASH 平台对象层面的特点 AS3 的语言特性需要对象支持 对象从 Object 基类集成 对象有类型判断 数据结构一般以对象为载体 临时对象作为参数,也需要 new 对象 容器 Array 和 Dictionary  中存储的是数值或者对象 使用引用来控制对象和属性 对象由底层控制其回收 (GC 操作  )
AS3 语言特点的代价 必须通过引用来控制对象 单个对象占资源量大 GC 操作无法控制 类型判断可有可无 属性访问有性能开销
优化办法 使用属性级的并联 例:需要实现以个 Unit 列表,每个元素都是一个 Unit 结构  public class Unit {   public var nShape:int;   public var nX:int; Public var nY:int; } ;
Version1: public class UnitArray { private var m_UnitArr:Array; public UnitArray(num:int) // 构造函数 {   m_UnitArr = new Array;   for(var i:int = 0 ; i < num ; i++)   {   m_UnitArr[i]=new Unit;   } } // 使用索引访问对象属性 public var GetUnit(idx:int):Unit {  return m_UnitArr[idx]; } } 假设包含 10000 个 UNIT  那么系统中保存的对象数量是  100001 个  (Num+1 个 ) 增加 UNIT  将改变对象数量
Version2 public class UnitArray {   public static const ATTR_SHAPE=0;   public static const ATTR_X=1;   public static const ATTR_Y=2;   private var nShapeArr:Array;   private var nXArr:Array;   private var nYArr:Array; public UnitArray(num:int) // 构造函数 {   nShapeArr = new Array(num);   nXArr = new Array(num);     nYArr = new Array(num); } …… // 使用索引访问对象属性 public function Get/SetShape(idx:uint,value:int); public function Get/SetX(idx:uint,value:int); public function Get/SetY(idx:uint,value:int); } 这种情况下 表示同样的数据内容对象开销仅为  ( 属性数量 +1) 增加一个 UNIT  并不改变总对象数量
Version3 public class UnitArray {   public static const ATTR_SHAPE:int =0;   public static const ATTR_X:int =1;   public static const ATTR_Y:int =2;   public static const ATTR_MAX:int = 3;   private var nAttrMap:Array=new Array[ATTR_MAX]; public UnitArray(num:int) // 构造函数 {   for(var i:int = 0;i<ATTR_MAX;i++)   {   nAttrMap[i]=new Array(num);   } } …… // 使用索引访问对象属性 public function GetAttr (idx:uint,Attr:int):int; public function SetAttr (idx:uint,Attr:int,value:int):void; } 这种情况下调整了对象访问形式可以更简单的组织数据
UnitArray  的本质 串行属性存储表示方法 并列属性存储表示 对象的本质是属性的集合,通过改变表示方式来构造对象 索引 nShape nX nY 0 1 500 500 1 2 432 324 2 3 113 321 3 3 567 212 4 2 323 433 5 1 211 12 … .
这种方法的使用条件 1  对象数量极多 2  对象属性总数必须比对象数量要少 3  放弃类型判断 4  适当调整访问形式 5  访问对象的形式可以用 ID 表示 6  带有 FreeList  性质的对象也可以使用 你可以获得的好处 1  用更少的内存达到相同目标 2  提高访问速度
性能测试 性能测试方式: 建立以个可以表示 100000 个对象的列表 结论是  VERSION2  比 VERSION1 占用更少的资源达到同样的目标。 VERSION2  是访问单个数组对象的操作 VERSION1  是访问单个数组对象后,还需要访问里面的属性。操作上多一步。 普通方法 并联方法 对象数 100009 10 访问速度 920ms 760ms
几种应用场合 基于 MAP+TILE 结构的地图 MAP 数据将包含  WIDTH*HEIGHT 数据量的 对象 如果 Width=200,Height = 100 那就需要 20000 个对象。 但是如果用并联形式,对象数量只依赖于 Map 单元格的属性数。大大降低对象的数量和访问速度
GUI 系统 GUI 系统是将每个控件的属性统一并联化,通过自定义实现的多组方法,来控制统一的属性。从而达到不同的表现。 比如对同一个 GUI 对象来说,可以通过判断其属性 Type 获得交互方式,渲染方式等内容。 并且一个控件不使用时,可以通过标记某个属性来进行资源回收。
MMO 中的玩家属性 MMORPG 中的玩家属性,是由服务器控制的。 玩家的消失和出现,会带有明显的资源释放和申请操作。资源流动量也比较大。会降低性能。 并联方法只要属性数量 < 同屏玩家数,就可以使用这种方法。
粒子系统 每个粒子数据结构相同。但是传统方法中,新建立一个粒子需要 NEW 一个对象。当粒子很多的时候,对象的出生和销毁将是个严重的负担。 使用并联属性方法后,同样的效果,不会增加任何内存开销。并且有更快的速度
总结 基于并联属性的对象优化技巧可以让程序以更小的开销达到相同的效果。同时也在一定程度上解决了 FLASH 对象数量无法控制和 GC 回收难以控制的问题。 但是这对程序编写者本人也提出了更高的要求。如果用的好,将对程序有很大的帮助。
谢谢大家

Flash基于对象的优化技术 黄炎中

  • 1.
  • 2.
    Overview MMOG 游戏中程序的对象需求FLASH 平台对象层面的特点 优化办法和评测 几个应用
  • 3.
    MMOG 游戏中程序的对象需求 高对象数量要求底层组件所需对象多 ( 图形 , 消息 , 网络 . 配置等等 ) 游戏内容庞大,需要以对象为载体实现 相同类型的对象数量也很多 对象数量增长很难预知 对象多导致内存占用量大 面向对象的编程方式决定了一切都要依赖对象
  • 4.
    FLASH 平台对象层面的特点 AS3的语言特性需要对象支持 对象从 Object 基类集成 对象有类型判断 数据结构一般以对象为载体 临时对象作为参数,也需要 new 对象 容器 Array 和 Dictionary 中存储的是数值或者对象 使用引用来控制对象和属性 对象由底层控制其回收 (GC 操作 )
  • 5.
    AS3 语言特点的代价 必须通过引用来控制对象单个对象占资源量大 GC 操作无法控制 类型判断可有可无 属性访问有性能开销
  • 6.
    优化办法 使用属性级的并联 例:需要实现以个Unit 列表,每个元素都是一个 Unit 结构 public class Unit { public var nShape:int; public var nX:int; Public var nY:int; } ;
  • 7.
    Version1: public classUnitArray { private var m_UnitArr:Array; public UnitArray(num:int) // 构造函数 { m_UnitArr = new Array; for(var i:int = 0 ; i < num ; i++) { m_UnitArr[i]=new Unit; } } // 使用索引访问对象属性 public var GetUnit(idx:int):Unit { return m_UnitArr[idx]; } } 假设包含 10000 个 UNIT 那么系统中保存的对象数量是 100001 个 (Num+1 个 ) 增加 UNIT 将改变对象数量
  • 8.
    Version2 public classUnitArray { public static const ATTR_SHAPE=0; public static const ATTR_X=1; public static const ATTR_Y=2; private var nShapeArr:Array; private var nXArr:Array; private var nYArr:Array; public UnitArray(num:int) // 构造函数 { nShapeArr = new Array(num); nXArr = new Array(num); nYArr = new Array(num); } …… // 使用索引访问对象属性 public function Get/SetShape(idx:uint,value:int); public function Get/SetX(idx:uint,value:int); public function Get/SetY(idx:uint,value:int); } 这种情况下 表示同样的数据内容对象开销仅为 ( 属性数量 +1) 增加一个 UNIT 并不改变总对象数量
  • 9.
    Version3 public classUnitArray { public static const ATTR_SHAPE:int =0; public static const ATTR_X:int =1; public static const ATTR_Y:int =2; public static const ATTR_MAX:int = 3; private var nAttrMap:Array=new Array[ATTR_MAX]; public UnitArray(num:int) // 构造函数 { for(var i:int = 0;i<ATTR_MAX;i++) { nAttrMap[i]=new Array(num); } } …… // 使用索引访问对象属性 public function GetAttr (idx:uint,Attr:int):int; public function SetAttr (idx:uint,Attr:int,value:int):void; } 这种情况下调整了对象访问形式可以更简单的组织数据
  • 10.
    UnitArray 的本质串行属性存储表示方法 并列属性存储表示 对象的本质是属性的集合,通过改变表示方式来构造对象 索引 nShape nX nY 0 1 500 500 1 2 432 324 2 3 113 321 3 3 567 212 4 2 323 433 5 1 211 12 … .
  • 11.
    这种方法的使用条件 1 对象数量极多 2 对象属性总数必须比对象数量要少 3 放弃类型判断 4 适当调整访问形式 5 访问对象的形式可以用 ID 表示 6 带有 FreeList 性质的对象也可以使用 你可以获得的好处 1 用更少的内存达到相同目标 2 提高访问速度
  • 12.
    性能测试 性能测试方式: 建立以个可以表示100000 个对象的列表 结论是 VERSION2 比 VERSION1 占用更少的资源达到同样的目标。 VERSION2 是访问单个数组对象的操作 VERSION1 是访问单个数组对象后,还需要访问里面的属性。操作上多一步。 普通方法 并联方法 对象数 100009 10 访问速度 920ms 760ms
  • 13.
    几种应用场合 基于 MAP+TILE结构的地图 MAP 数据将包含 WIDTH*HEIGHT 数据量的 对象 如果 Width=200,Height = 100 那就需要 20000 个对象。 但是如果用并联形式,对象数量只依赖于 Map 单元格的属性数。大大降低对象的数量和访问速度
  • 14.
    GUI 系统 GUI系统是将每个控件的属性统一并联化,通过自定义实现的多组方法,来控制统一的属性。从而达到不同的表现。 比如对同一个 GUI 对象来说,可以通过判断其属性 Type 获得交互方式,渲染方式等内容。 并且一个控件不使用时,可以通过标记某个属性来进行资源回收。
  • 15.
    MMO 中的玩家属性 MMORPG中的玩家属性,是由服务器控制的。 玩家的消失和出现,会带有明显的资源释放和申请操作。资源流动量也比较大。会降低性能。 并联方法只要属性数量 < 同屏玩家数,就可以使用这种方法。
  • 16.
    粒子系统 每个粒子数据结构相同。但是传统方法中,新建立一个粒子需要 NEW一个对象。当粒子很多的时候,对象的出生和销毁将是个严重的负担。 使用并联属性方法后,同样的效果,不会增加任何内存开销。并且有更快的速度
  • 17.
    总结 基于并联属性的对象优化技巧可以让程序以更小的开销达到相同的效果。同时也在一定程度上解决了 FLASH对象数量无法控制和 GC 回收难以控制的问题。 但是这对程序编写者本人也提出了更高的要求。如果用的好,将对程序有很大的帮助。
  • 18.