基于垃圾回收的资源管理

基于垃圾回收的资源管理

游戏中有大量的资源数据,这部分数据通常数以百兆,甚至上G。如何在运行时管理好这些数据,也是游戏软件相对其他许多软件的一大难题。

管理这些资源分为加载和Cache两个方面。对于资源数量比较少的游戏,我们可以采用只加载不释放的方式,即使资源总量大于物理内存数,OS 在虚拟内存的管理方面也自然有它的优势。至于加载的时机,为了追求用户玩的时候的流畅体验,我们可以在一开始就进行 loading。当然也可以为了减少 loading 时间,去做动态加载。动态加载的问题比较复杂,可能涉及多线程,以及预读操作。这篇 blog 不展开谈。前段时间写过一篇动态加载资源 可以参考。

如果总的资源数很大的时候,我们就需要 cache 管理。因为在 32 位 OS 下,虚拟地址空间是有限的。这里主要谈 cache 的管理。

最近我实现的一套方案是基于 gc 的。首先需要一套内存分配器,首先向 OS 索取整块的大块内存(例如一次 8M),然后使用这个自己的内存分配器在这大块内存上再管理。这个内存分配器可以实现的相对简单。因为我们将使用 gc ,不再需要 free 函数。只需要分开管理好大块内存和小块内存,提供足够的效率就可以了。

当申请的内存堆不够用时,可以有两种策略对待。其一是向 OS 索取新的内存块,其二就是 gc 。这两个策略应当根据实际情况结合使用。

gc 使用根扫描并标记的算法。用户逻辑层维护一个或几个资源的根。gc 发生时根开始做标记工作。如果正确的进行这一步,我的方法是,所有从受 gc 管理的堆中分配出来的内存,它们的 cookie 上都记录有一个 mark 函数地址。这个函数用于标记这个内存块中可能出现的相关块。mark 函数只需要每个不同的类定义一个,并在 new 出对象时注册到 cookie 上。这些对象的 new 自然是被重载过的,用于从受 gc 管理的内存堆中分配内存块出来。至于 POD 类型,注册一个空函数指针就够了。

为了实行 cache 的管理,每个被分配出来的内存块还应该设置一个 id 。我们可以通过 id 来检索出内存块地址。这样,在通过 cache 读取资源的时候,每个资源都分配一个 id ,存放在受管理的内存堆中。这些资源都不需要主动释放。一旦发生 gc ,正在使用的资源将在根扫描流程被标记。其它的资源会被回收掉。同时, id 映射表也应该在 gc 完毕后被正确的设置。

当然资源本身的关联关系错综复杂的时候,这种方法在算法简洁度上要优于引用计数的算法。而且资源占用的物理内存往往因为更加连续而得到更大的利用率。cache 的容量也更加容易控制。

我的带 gc 的内存分配器的接口大约是这样定义的(以下由实际的代码经过修改):

<span class="c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">struct</span> <span class="c_StructOutline def_Outlined def_Special">i_gc_allocator</span>
<span class="def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">{</span></span>
    <span class="c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">virtual</span> <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">void</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">*</span> <span class="c_FuncOutline def_Outlined def_Special">malloc</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">(</span></span>
          <span class="c_KeywordStdio c_KeywordStructure def_StructKeyword def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">size_t</span> size<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">,</span>
          <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">unsigned</span> id<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">,</span>
          <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">void</span> <span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">(</span></span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">*</span>mark_func<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">)</span></span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">(</span></span><span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">void</span> <span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">*</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">,</span> <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">void</span> <span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">(</span></span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">*</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">)</span></span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">(</span></span><span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">void</span> <span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">*</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">)</span></span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">)</span></span>
    <span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">)</span></span> <span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">=</span> <span class="def_NumberDec def_Number" style="color: rgb(0, 140, 0);">0</span><span class="c_StructureSymbol def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);">;</span>
    <span class="c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">virtual</span> <span class="c_KeywordStdio c_KeywordStructure def_StructKeyword def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">size_t</span> gc<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">(</span></span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">)</span></span> <span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">=</span> <span class="def_NumberDec def_Number" style="color: rgb(0, 140, 0);">0</span><span class="c_StructureSymbol def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);">;</span>
    <span class="c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">virtual</span> <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">void</span> expand<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">(</span></span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">)</span></span> <span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">=</span> <span class="def_NumberDec def_Number" style="color: rgb(0, 140, 0);">0</span><span class="c_StructureSymbol def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);">;</span>
    <span class="c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">virtual</span> mark<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">(</span></span><span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">void</span> <span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">*</span>root<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">)</span></span> <span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">=</span> <span class="def_NumberDec def_Number" style="color: rgb(0, 140, 0);">0</span><span class="c_StructureSymbol def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);">;</span>
    <span class="c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">virtual</span> <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">void</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">*</span> <span class="cpp_KeywordSTL c_KeywordStdio c_KeywordStructure def_StructKeyword def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">find</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">(</span></span><span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">unsigned</span> id<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">)</span></span> <span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">=</span> <span class="def_NumberDec def_Number" style="color: rgb(0, 140, 0);">0</span><span class="c_StructureSymbol def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);">;</span>
<span class="def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);">;</span>

这里只提供了 malloc 来分配内存。并且可以在分配内存的同时给内存块赋予 id。以后可以通过 find 来找回内存。当我们频繁加载资源的时候,这可以用来保证每份资源都唯一的被加载一次。 expand 用来向 OS 申请新的内存块。 mark 函数可以从一个 root 内存块开始标记。而 gc 就用于回收内存堆。它有一个返回值,表示 gc 完成后内存中还有多少残留数据。这可以用来作为是否要调用 expand 的一个参考。这个接口用于比较底层的控制,真正使用时还需要进一步的封装。

对于一般的 POD 类型,只用简单的调用 malloc(size,id,0) 就可以了。复杂的类型可以按如下实现:

<span class="c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">class</span> <span class="cpp_ClassOutline c_StructOutline def_Outlined def_Special">gcdata </span><span class="def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">{</span></span>
    <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">void</span> <span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">*</span>data<span class="c_StructureSymbol def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);">;</span>
    <span class="c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">static</span> <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">void</span> <span class="c_FuncOutline def_Outlined def_Special">mark</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">(</span></span><span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">void</span> <span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">*</span>addr<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">,</span><span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">void</span> <span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">(</span></span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">*</span>m<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">)</span></span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">(</span></span><span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">void</span> <span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">*</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">)</span></span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">)</span></span> <span class="def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">{</span></span>
        gcdata <span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">*</span>self<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">=</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">(</span></span>gcdata<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">*</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">)</span></span>addr<span class="c_StructureSymbol def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);">;</span>
        m<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">(</span></span>self<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">-</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">></span>data<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);">;</span>
    <span class="def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">}</span></span>
<span class="c_Label def_Label" style="color: rgb(227, 74, 220);"><span class="c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">public</span>:</span>
    <span class="c_FuncOutline def_Outlined def_Special">gcdata</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">(</span></span>i_gc_allocator <span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">*</span>gc<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">)</span></span> <span class="def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">{</span></span>
        data<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">=</span>gc<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">-</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">></span>malloc<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">(</span></span><span class="def_NumberDec def_Number" style="color: rgb(0, 140, 0);">100</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">,</span><span class="def_NumberDec def_Number" style="color: rgb(0, 140, 0);">0</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">,</span><span class="def_NumberDec def_Number" style="color: rgb(0, 140, 0);">0</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);">;</span>
    <span class="def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">}</span></span>
    <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">void</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">*</span> <span class="c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">operator</span> <span class="c_FuncOutline def_Outlined def_Special"><span class="c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">new</span></span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">(</span></span><span class="c_KeywordStdio c_KeywordStructure def_StructKeyword def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">size_t</span> s<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">,</span><span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">unsigned</span> id<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">,</span>i_gc_allocator <span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">*</span>gc<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">)</span></span> <span class="def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">{</span></span>
        <span class="c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">return</span> gc<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">-</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">></span>malloc<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">(</span></span>s<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">,</span>id<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">,</span>mark<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);">;</span>
    <span class="def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">}</span></span>
    <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">void</span> <span class="c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">operator</span> <span class="c_FuncOutline def_Outlined def_Special"><span class="c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">delete</span></span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">(</span></span><span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">void</span> <span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">*</span>p<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">,</span><span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">unsigned</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">,</span>i_gc_allocator <span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">*</span>gc<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">)</span></span> <span class="def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">{</span></span><span class="def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">}</span></span>
<span class="def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);">;</span>

我们这里给出了一个想受到 gc 管理的资源类型的例子:gcdata 。这个对象中有一个成员变量 data 指向一块另外分配出来的长度为 100 字节的内存。这里的 mark 函数就用于标记对象中gcdata 这个自行申请的内存块 data。它使对象被扫描时,data 可以一起被扫描到。

gcdata <span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">*</span>obj<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">=</span><span class="c_KeywordANSI def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">new</span> <span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">(</span></span>id<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">,</span><span class="cpp_KeywordSTL c_KeywordStdio c_KeywordStructure def_StructKeyword def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">allocator</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">)</span></span> gcdata<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">(</span></span><span class="cpp_KeywordSTL c_KeywordStdio c_KeywordStructure def_StructKeyword def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">allocator</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);">;</span>

当我们通过 allocator 构造出这个对象时,对象占用的内存就会受到管理。

<span class="cpp_KeywordSTL c_KeywordStdio c_KeywordStructure def_StructKeyword def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">allocator</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">-</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">></span>mark<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">(</span></span>obj<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);">;</span>
<span class="cpp_KeywordSTL c_KeywordStdio c_KeywordStructure def_StructKeyword def_Keyword" style="color: rgb(230, 97, 112); font-weight: bold;">allocator</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">-</span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);">></span>gc<span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairStart def_Special" style="color: rgb(170, 68, 68);">(</span></span><span class="c_Symbol def_Symbol" style="color: rgb(107, 102, 39);"><span class="def_PairEnd def_Special" style="color: rgb(170, 68, 68);">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol" style="color: rgb(176, 96, 176);">;</span>

在 gc 前调用 mark 将保证 obj 对象不会被回收掉。

这个 gc 模块并不去整理内存,分配出来的内存不会再移动了,这可以简化很多设计。

COMMENTS

应该加上个mark内存移动管理,否则还是有可能产生大量的小碎片的,影响到内存的分配.其实java虚拟机的实现代码就是这样管理的,我自己没做过不好说,仅仅建议一下

多线程的问题不在这里讨论范围之内。以上代码只是示意。

ps. 扫描的过程是很快的。

你在扫描的时候不加锁的吗?

既然你读了我的书,那么你这个问题在书上 208,209 页有详细分析。

另外,最好不要在 blog 上发主题无关的回复,我有专门的留言本的 :)

云风,看了您的书感受非常深。最近想学习用vc内嵌汇编使用mmx指令优化内存存取,但遇到一个非常辣手的问题,希望您能够帮我看看。

#include"windows.h"
#include<iostream>
using namespace std;


void fn16(unsigned char *mem1,unsigned char *mem2,unsigned long dwSize)
{

_asm
{
pushf 
mov ecx,dwSize
mov esi,mem1
mov edi,mem2
///mmx优化部分//
again2:
cmp ecx,16 //是否比16字节大
jl notbeggerthan16
movq mm0,[esi]
movq mm1,[esi+8]
movq [edi],mm0
movq [edi+8],mm1
add esi,16
add edi,16 
sub ecx,16
jmp again2

notbeggerthan16:
cmp ecx,8
jl notbeggerthan8
movq mm0,[esi]
movq [edi],mm0
add esi,8
add edi,8
sub ecx,8
jmp notbeggerthan16
非mmx优化部分/
notbeggerthan8:
start8:
cmp ecx,0
jz end
mov ax,[esi] //假设内存大小是16的倍数
add esi,2
mov [edi],ax
add edi,2
sub ecx,2
jmp start8
end:
emms
popf
}//end _asmsm

}

void main()
{
SYSTEMTIME st;
GetSystemTime(&st);
unsigned long timeBegin0=st.wSecond;
unsigned long timeBegin=st.wMilliseconds;
unsigned char *mem1=new unsigned char[2048*2000];
unsigned char *mem2=new unsigned char[2048*2000];

for (int i=0;i<=100;i++)
{
fn16(mem1,mem2,2048*2000);
}

GetSystemTime(&st);
unsigned long timeEnd0=st.wSecond;
unsigned long timeEnd=st.wMilliseconds;

unsigned long pass=(timeEnd0-timeBegin0)*1000+timeEnd-timeBegin;
cout<<pass;
}

以上程序负责把mem1中dwSize个字节的数据传入mem2。实验后发现:
当所传字节数在2048*500左右的时候,使用mmx后明显快近一倍的速度。而当dwSize>2048*2000的时候 却没有什么区别。不知道为何。

我对比的方法是:把“优化部分///”和“//非优化部分///”之间的部分注释掉即为非优化的程序。通过看循环100次的时间差来判断快慢。

云风,windows vista今年又可能开始卖了.程序员应该如何面对新的挑战呢?又要如何做好准备呢?
你能写篇文章谈谈你的观点吗?

"并不去整理内存,分配出来的内存不会再移动了"

没看懂挖。
8M一块,是不是等8M里面没有正在使用的内存块的时候释放这个8M,否则整个8M都留下?
申请内存的时候先去已有的这些个8M里分配,不行的话就expand?

明白你的意思了。
按照这个思路到了内存空间不足的时候就是整体清除再来过了吧

gc 不整理内存,所以只是扫描一下。速度跟内存块的个数有关,而不会移动大块内存,所以不会有停顿感。

怎么解决在gc时候的停顿呢?

内存块全部是一个接一个放在整块内存中的。根扫描就是用来标记被使用块,除掉被使用块,剩下全部是可以被释放的。

内存碎片是内存管理程序都会产生的,如何避免是内存管理模块的工作。这种 gc 会延缓内存释放的操作,可以进一步缓解内存碎片的产生。

不整理内存,随着分配和释放的不断进行,会很快产生很多内存碎片,导致缓存块虽有足够空间却无法满足分配对象的请求,这时就把整块内存都释放?

没看明白你说的回收动作是如何进行的,如果说gc时候正使用的资源被标记其他的被gc,那么你一定还有判断资源有没有被使用的方式,是否仍类似于引用计数?
效率上不去说,理解上没有引用计数容易理解...^_^

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值