游戏乐悠悠网游开发网

 找回密码
 立即注册
查看: 1332|回复: 0
打印 上一主题 下一主题

window 下 Unreal3 的内存管理(二)

[复制链接]
  • TA的每日心情
    无聊
    2014-8-8 12:31
  • 签到天数: 37 天

    [LV.5]常住居民I

    鲜花(0) 鸡蛋(0)
    跳转到指定楼层
    楼主
    发表于 2012-2-26 08:38:02 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    2.加快内存分配速度。$ J+ z/ {- w& H( Z- q3 i5 z

        我的个人理解一个好的内存分配器,1要分配内存块,2要释放内存块,3减少碎片。这3个是起码的,当然你可以加GC功能,在内存管理这本书里面讲了2个GC方法(作者应该很牛逼,他说他所有讲的内存管理都是最简单,为说明问题,代码没有一点优化,否则就会晦涩难懂,还好U3并没有写成这样)
    " i# M# {/ @$ V( h* D; H
        我先说说我以前遇到几种内存管理方法,一个很大的问题,就是当内存申请不够用了的时候,再申请一块的时候,都没讲怎么处理。都是预先分配一个大的,如果不够用了怎么办?还有就是,内存碎片很难处理,因为你做内存整理,牵扯到指针的移动的改变,做这个真是费力不讨好,速度就要有限制,还有有空间来配合做移动。其余的就是速度和空间上的交换了。所以这些方法都很难找到平衡点,没有一个最有效折中的方法。
    6 H7 u  j' X2 |, J. h
        当然U3也并没有做到你想像的那么好,但它做的比较平衡。性价比高。. B! y- e' C$ L! \# y

        先说几个统计性的数据,在游戏中,小于1K的动态分配数据是最频繁的,而且越小越频繁。相反越大的数据,例如模型VB,IB,texture数据等等吧,这些申请和释放频率比较低,很大多数动态分配时间都浪费到小数据的申请和释放上。有2种比较内存管理机制,一个是典型的空间换时间,就是一个内存块,我分成相等的小块,根据某种机制正好要在这个里面分配,那么不管这个小块大于要申请的size多大,都要拿出一个小块。比如我一个内存块是40,我分成4块,每个大小是10.我现在要分配6,那么取出一个小块,多出那个4就要被浪费掉了。还有一种机制就是有多大我就分多大的,然后用链表或者树结构管理空间和占用的块。这种方法经过多次申请释放会有很多碎片是不可用的。第一种机制,分配释放都很块,因为这个是等大的可以做类似数组那么用索引来出来,申请释放。而第2种机制申请和释放去查找,比较浪费时间。
    5 l4 |; Q; T4 o4 L. F( e, F
        U3方法用的是第一种机制,最重要的是,它巧妙应用了操作系统的特性。如果大块内存也申请释放相对比较频繁的话,可以把大块内存这个用第二种方法处理。但这个频繁要多么频繁,好像很难给出准确数据,因为所有的时间消耗都是小块内存数据申请上,所以我感觉不用也可以。/ ~; x5 q. N, {2 W5 n4 L5 b
    4 b; T9 o. }5 r1 A
        说了这么多,现在言归正传,详细分析U3在windows下的内存管理,因为U3支持多个平台,每个平台下的内存管理是不一样,这个也是针对不同平台的特性定制的,后面你就会发现,这个Windows下的内存管理,巧妙的运用了windows内部原理。

        (这里我改了好几遍,不知道怎么说好,这些说原理吧,首先是不容易说明白,看的人一定也一头雾水,最后还是把代码弄上来,分析代码,这样说的能比较透彻。有unreal代码的自己去找FMallocWindows.h这个文件)+ o. a9 O- g1 i1 \( i
    , r2 Z7 i' {$ Q' F0 C. O
    struct FPoolInfo$ U8 C6 c, [. V$ V. O; |' X$ V
    {
      DWORD     Bytes;  // Bytes allocated for pool.( P+ f" Y8 v/ q# A5 L! o
      DWORD  OsBytes; // Bytes aligned to page size.5 g9 O$ \) b" w2 L* R. Y# B% s
      DWORD       Taken;      // Number of allocated elements in this pool, when counts down to zero can free the entire pool." q) G* p5 m8 O* \. l
      BYTE*       Mem;  // Memory base.
      FPoolTable* Table;  // Index of pool.* q4 m* k/ T: Y0 H% R/ V
      FFreeMem*   FirstMem;   // Pointer to first free memory in this pool.
      FPoolInfo* Next;( @; O0 P9 ^$ a& W5 |% k5 z# e
      FPoolInfo** PrevLink;
    4 O( |& k6 ~$ s) ]& |6 C
      void Link( FPoolInfo*& Before )0 F- [8 {; \, p# X" D
      {: r5 ^' D# r3 b* c1 X! g
       if( Before )$ g9 ]+ r. L# H* z6 g0 U9 J/ d
       {
        Before->revLink = &Next;8 g' X/ t( B% G: v! n' m$ B6 l
       }
       Next     = Before;3 L9 v  f" X. R6 j+ [; ~3 L* T2 I
       PrevLink = &Before;: G! u8 L# k1 n4 }- d! d
       Before   = this;
      }
      void Unlink()
      {. D! i- }8 R! h
       if( Next )
       {$ F7 K5 q6 P+ }- a9 v2 O
        Next->revLink = PrevLink;
       }3 I6 z8 Z* M0 |) r+ l2 \
       *PrevLink = Next;
      }
    };
    & {2 }  n6 f' Z2 W  o9 q$ ], b
    // Information about a piece of free memory. 8 bytes." E+ b% T8 Y' Y1 N5 q' {: @7 g
    struct FFreeMem9 w" G1 T7 c$ x! q: a& I+ U, V
    {1 _6 j! h4 v4 o/ \
      FFreeMem* Next;  // Next or MemLastPool[], always in order by pool.- [5 o7 B" r# G# F6 E! i) v
      DWORD  Blocks;  // Number of consecutive free blocks here, at least 1.
      FPoolInfo* GetPool()0 o5 I( M' T) b+ O4 `" l
      {! J& o, M1 E4 m- k2 k; G9 O, @8 b
       return (FPoolInfo*)((INT)this & 0xffff0000);
      }. h, \" V. G) O: z
    };
    : n# S8 b+ o: t8 j/ M& c
    // Pool table.4 b; ~$ j0 _7 y
    struct FPoolTable, ?+ w: z4 h' A. X) l' y& P( }, \
    {: c7 b+ w. {( f+ b. L- V
      FPoolInfo* FirstPool;   //所有小块没都分配出去的FPoolInfo列表
      FPoolInfo* ExhaustedPool;//所有小块都分配出去的FPoolInfo列表
      DWORD      BlockSize;//一次申请分配,能分配的内存大小(也就是说小块内存大小)
    };
      B% U/ Q' o6 ^$ s# a
    当分配一个大块内存的后,这个大块内存地址会记录到FPoolInfo的  BYTE*       Mem这个变量,每个FPoolInfo都要归属于一个FPoolTable,也就是说FPoolTable管理能分配小块内存都等于BlockSize的所有FPoolInfo。开始创建这个大块内存的时候,同时这个FPoolInfo也被创建,进入FPoolInfo* FirstPool列表,如果这个FPoolInfo小块内存(上面讲的第一种机制,大块会切分相等小块,小块就是去分配的,小块的大小是FPoolTable的BlockSize变量)都分配完毕,那么就进去ExhaustedPool链表。

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    小黑屋|手机版|Archiver|Online Game Xingbarking Dev Team  

    GMT+8, 2024-11-24 08:34 , Processed in 0.136078 second(s), 34 queries .

    Powered by Discuz! X3.2 Licensed

    © 2001-2013 Comsenz Inc.

    快速回复 返回顶部 返回列表