专利名称:在运行时对堆数据进行池分配的方法
技术领域:
本发明涉及内存分配领域,特别涉及在运行时对堆数据进行池分配的方法。
背景技术:
随着处理器技术的快速发展,处理器速度和存储系统之间的速度差已经越来越大。存储系统的速度正成为计算机整体运行速度进一步提高的瓶颈。为了提高存储系统的速度,现有技术中提出了多种方法,其中的提高数据的局部性的方法可以在不增加带宽需求的情况下提高存储系统的性能,因而得到了广泛的应用。
堆(heap)是程序内存空间中的一块区域,程序运行时动态需要的内存是从堆中进行分配的。例如C程序通过malloc和calloc等系统函数从堆中申请内存,用free函数将申请的内存释放回堆中;C++程序通过new操作申请,通过delete操作释放;Java程序也通过new操作申请,但是通过垃圾收集器(Garbage Collector,GC)来自动释放不再使用的内存。在很多程序中,堆数据占据了总数据的很大一部分,因此对堆数据进行数据布局,对于提高数据的局部性,进而提高存储系统的性能具有很重要的意义。
以参考文献1“X.Huang,S.M.Blackburn,K.S.McKinley,J.E.B.Moss,Z.Wang,and P.Cheng.The garbage collection advantage,improving programlocality.In Conference on Object Oriented Programming Systems Languagesand Applications,pages 69-80,2004”为代表的很多现有的堆数据布局方法的实现依赖于垃圾收集器(Garbage Collector,GC),由于GC可以在运行时移动对象并更新它的相关引用,因此它可以根据需要动态进行数据布局的工作。然而很多程序在运行时得不到GC的支持,此时由于别名的存在将不能保证更新被移动数据的所有相关引用,所以在这种情况下移动一个数据对象可能会引起程序错误。因此,为了避免程序出错,在分配数据时就应当考虑数据的局部性,并把它们从合适的位置分配。池分配(PoolAllocation)是数据分配的一种方法,池分配是把所有堆数据对象分成不同的组,分配堆数据对象时从所在组的“内存池”(Memory Pool,一段连续的内存空间)里分配,以提高组内的数据对象的局部性。参考文献2“C.Lattner and V.Adve.Automatic pool allocationImproving performance bycontrolling data structure layout in the heap.In Conference on ProgrammingLanguage Design and Implementation,pages 129-142,2005”所公开的一种现有的池分配方法是在编译器中使用启发式方法识别属于同一个数据结构(如链表的所有节点,树的所有节点等)的堆数据对象,然后把它们从同一个内存池里分配。这种方法依赖于程序源代码和特定的编译器。
参考文献3“S.Rubin,R.Bodik,and T.M.Chilimbi.An efficient profileanalysis framework for data-layout optimizations.In Annual Symposium onPrinciples of Programming Languages,pages 140-153,2002”所公开的另外一种事先训练的方法可以获得频繁的访存模式等信息,为各种优化(包括池分配)提供依据。这种方法需要一次或多次专门的运行来进行训练,而且训练也需要寻找有代表性的输入集。
参考文献4“Q.Zhao,R.Rabbah,andW.Wong.Dynamic memoryoptimization using pool allocation and prefetching.ACM SIGARCH ComputerArchitecture News,33(5)27-32,2005”所公开的现有动态池分配方法在运行时把从同一个调用内存分配函数(如malloc)的调用点(以下简称调用点)分配的对象分在同一组,从同一个内存池中分配。这种方法没有对运行时环境、源代码或训练的依赖,对用户透明。但是内存分配点和内存池是一一对应的关系,不够灵活,不能适应以下一些常见的情况。
一种情况是一些关系不紧密的堆数据对象可能会从同一个调用点分配。例如,程序员经常在分配内存时使用包装函数来增强程序的健壮性。包装函数调用系统的分配函数,并检查返回的指针是否是合法值,图1给出了包装函数的一个示例。当使用包装函数时,它包含的调用点分配的堆数据对象是由包装函数的调用者决定的,因此这些对象可能完全无关,但是按照文献4的方法它们会从同一个池里分配。例如在SPEC2000的175.vpr,176.gcc,253.perlbmk,300.twolf等例子中,几乎所有的内存分配都是通过调用两个包装函数(一个包装malloc,一个包装calloc)来实现的,因此这几个例子分配的大部分内存都集中在两个池里。这种分配结果和使用默认的分配函数相比并没有太大改进,不能发挥池分配的优势。
另一种情况是一些关系紧密的堆数据对象可能会从不同的调用点分配。这种情况可能是程序员的意图(例如程序员在程序的多个位置分配节点的内存,并把节点插入同一个链表),也可能是由编译器优化产生(例如编译器对包含内存分配的循环进行循环展开)。按照文献4的方法,这些对象会根据调用点不同而分散到多个池里。但是实际上,更好的分配方案是把这些关系紧密的堆数据对象从同一个池里分配。
发明内容
本发明的目的是克服现有技术不能解决关系不紧密的堆数据对象因为在同一个调用点分配而从同一个内存池分配的问题以及关系紧密的堆数据对象因为在不同的调用点分配而从不同的内存池分配的问题,从而提供一种在运行时对堆数据进行池分配的方法。
为了实现上述目的,本发明提供了一种在运行时对堆数据进行池分配的方法,包括 步骤1)、接收堆数据的内存池分配请求; 步骤2)、考察调用点上下文,将包含在包装函数中的所述调用点的地址和调用最上层包装函数的调用点的地址加入变长调用链; 步骤3)、为从所述变长调用链所分配的堆数据对象选择内存池; 步骤4)、从所述内存池中为所述堆数据分配空间。
上述技术方案中,所述的步骤3)包括分析变长调用链所分配的堆数据对象,为具有紧密关系的堆数据对象分配同一个内存池,为不具有紧密关系的堆数据对象分配不同的内存池。
上述技术方案中,所述的步骤3)包括 步骤3-1-1)、分析从所述变长调用链所分配的堆数据对象的指针信息; 步骤3-1-2)、从该变长调用链所分配的堆数据对象A和从另一变长调用链所分配的堆数据对象B具有相同的类型,并且所述A的指针保存在所述B的某个域中,所述A和B具有紧密关系,共用一个内存池。
上述技术方案中,所述的步骤3)包括 步骤3-2-1)、分析从所述变长调用链所分配的堆数据对象的指针信息; 步骤3-2-2)、从该变长调用链所分配的堆数据对象A的指针记录在一组对象C的某个域里,而从另一变长调用链所分配的堆数据对象B的指针也保存在这组对象C的同一个域里,并且所述A和B的类型相同,所述A和B具有紧密关系,共用一个内存池。
上述技术方案中,所述的步骤3)包括 步骤3-3-1)、分析从所述变长调用链所分配的堆数据对象的指针信息; 步骤3-3-2)、从该变长调用链所分配的堆数据对象不和从任何其它变长调用链所分配的堆数据对象共用一个内存池,新建一个内存池。
上述技术方案中,所述的步骤2)包括 步骤2-1)、用当前的调用点的地址查找包装函数表,构造变长调用链;所述包装函数表记录了已知的包装函数的信息; 步骤2-2)、用所述变长调用链查找映射表,在无法从所述映射表中找到与该变长调用链所对应的内存池的信息时,执行下一步;所述映射表保存了变长调用链与内存池之间的对应关系; 步骤2-3)、根据调用点的地址上下文确定变长调用链,并更新所述的包装函数表。
上述技术方案中,所述的步骤2-1)包括 步骤2-1-1)、初始化变长调用链为空; 步骤2-1-2)、将当前调用点的地址加入变长调用链中; 步骤2-1-3)、如果当前调用点的地址在包装函数表中,则把上一层调用点变为当前调用点,然后重新执行步骤2-1-2),否则,执行步骤2-2)。
上述技术方案中,所述的步骤2-3)包括 步骤2-3-1)、初始化这次内存分配请求的变长调用链为空; 步骤2-3-2)、将当前调用点的地址加入变长调用链中; 步骤2-3-3)、如果分配的内存对象的指针没有被存到全局变量或堆中某个位置,而被当前调用点所在的函数返回到上一层调用点时,把当前调用点的地址写入所述包装函数表中,上一层调用点变为当前调用点,然后重新执行步骤2-3-2),否则执行步骤3)。
上述技术方案中,所述的步骤3)还包括 将所述变长调用链与为该变长调用链所分配的内存池之间的对应关系更新到所述映射表中。
上述技术方案中,所述的步骤4)包括 步骤4-1)、池分配器统计所述内存池的分配次数; 步骤4-2)、当内存池的分配次数小于第一门限时,使用系统内存分配器进行分配,否则,执行下一步; 步骤4-3)、内存池的分配次数已经达到了第一门限,进一步判断之前分配的对象大小是否超过了第二门限,当超过时,使用系统内存分配器进行分配,当没有超过时,从段中分配。
上述技术方案中,所述的从段中分配包括 步骤4-3-1)、当内存池的分配次数刚达到设定门限后,该内存池从系统申请一块段; 步骤4-3-2)、该内存池需要分配对象时,从段中分配; 步骤4-3-3)、如果当前的段使用完毕,则申请一个新段; 步骤4-3-4)、当一个段中的对象都被释放后,段被系统回收。
本发明的优点在于 本发明能够解决关系不紧密的堆数据对象因为在同一个调用点分配而从同一个内存池分配的问题以及关系紧密的堆数据对象因为在不同的调用点分配而从不同的内存池分配的问题,提高了池分配的效果。
图1为关系紧密的堆数据的示例图; 图2为本发明的在运行时对堆数据进行池分配的方法的流程图。
具体实施例方式 下面结合附图和具体实施方式
对本发明的方法加以说明。
在背景技术的描述中已经知道,参考文献4所公开的动态池分配方法在使用包装函数时,会遇到关系不紧密的堆数据对象因为在同一个调用点分配而从同一个内存池分配的问题,以及关系紧密的堆数据对象因为在不同的调用点分配而从不同的内存池分配的问题。因此,下文将就本发明如何解决上述两个问题分别予以说明。
关系不紧密的堆数据对象从同一个内存池分配的问题 为了便于理解,在此做举例说明。例如在下面表1的一段程序中,使用了一个包装函数safe_malloc(1行-8行)。在main函数中,第100行通过调用safe_malloc为一个链表分配了新节点,第200行通过调用safe_malloc为一棵树分配新叶子。
表1 如参考文献4中所提到的现有技术在接到内存分配请求时,仅仅使用内存分配函数malloc的直接调用地址(第2行)来作为所分配对象的特征,这样会把前面所提到的需要新分配的链表节点和树的叶子在同一个池里分配。但是很显然它们属于不同的数据结构,互相之间的关系并不紧密。因此,能代表它们特征的调用点还应该包括包装函数的调用点(分别为第100行和第200行),从而形成由内存分配函数malloc的直接调用地址与包装函数的调用点共同组成的用于内存分配的调用链。当采用上述调用链时,链表节点和树的叶子就可以被正确识别到两个池里。在上面所提到的例子中,所述调用链的长度为2,也就是调用链的最后2个调用点(即100行和2行(链表节点),或者200行和2行(树的叶子))用于实现内存分配。有时候,程序中一个包装函数里可能调用另一个包装函数,这时应该使用的调用链的长度会更长,这样才能找到不在包装函数里的有意义的调用点。
基于上述理由,本发明可将调用链的长度设置为可变长度,通过可变长度的调用链来消除包装函数的不良影响。具体的说,当接到内存分配请求时,首先取得内存分配函数的直接调用地址(上例中的2行);然后分析该地址所属函数(safe_malloc)在内存分配函数结束后对返回的堆数据对象的操作(3行-7行),如果该函数没有将该对象指针存入全局变量或堆中的某个位置,而只是把该指针返回上一层调用点时(7行),就认为该函数是包装函数,变长调用链的长度需要增加,以包括该函数的调用者(例如100行或200行);重复上述函数判断以及变长调用链长度增加的过程,直到调用者不再是包装函数为止(这个例子中,main函数不是包装函数,因此调用链长度增加到2之后就不再增加了)。
为了避免对一个调用点多次识别是否为包装函数,作为一种优选实现方式,可以将已经识别出的包装函数保存在一个表(称作包装函数表)中。在构造变长调用链时,先查找包装函数表,如果该表中没有所要识别的包装函数,再进行上述的识别过程。这一优选实现方式能够降低构造变长调用链的开销。
从上面的描述可以看出,与以参考文献4为代表的现有技术中每个调用点对应一个内存池明显不同的是,本发明中每个变长调用链对应一个内存池,这个内存池可能是该变长调用链所独有的(如上面例子中的简单情况),也可以是和其它变长调用链共享的(参考下文所描述的池合并的情况)。变长调用链与内存池之间的对应关系可以保存在一个映射表中。在运行时,分配器每次得到分配请求时,先构造该请求的变长调用链,然后再查找这个映射表,得到对应的内存池,再从中进行分配。在一个优选实现方式中,为了省略查表操作,另一种方法是在各个变长调用链的最上层调用点之前,利用插桩把它对应的内存池id存到一个全局变量v中。这样,当程序从该变长调用链调用到动态内存分配函数时,直接查看全局变量v就可以得到对应的内存池,不必再进行查表。这种插桩只在能够保证下一次调用一定具有该变长调用链时才进行。
关系紧密的堆数据对象从不同的内存池分配的问题 在对如何解决关系紧密的堆数据对象从不同的内存池分配的问题做详细说明前,首先对关系紧密的堆数据对象这一概念加以说明。为了方便理解,下面结合图1所示的例子对相关概念加以说明。
在图1所示的例子中,包括有一个链表,该链表有三个节点,各个节点上包括有三个域(即图中被分为三段的白色方块)两个指针域d1和d2,分别指向动态分配的数据(灰色方块和斜线方块);一个指针域next,指向链表的下一节点。
通过对堆数据对象的分析,本发明中定义了两种关系紧密的模式。第一种模式是如果对象A和对象B具有相同的类型,并且A的指针保存在B的某个域中,则A和B很可能属于同一个数据结构,它们之间的关系也是紧密的。例如图1中,链表的各个节点就满足这一种模式。第二种模式是如果对象A的指针记录在对象C的某个域里(A和C的类型可以不同),而对象B的指针也保存在对象C的同一个域里,并且A和B的类型是相同的,则A和B可能是同一个数据结构中的同一个动态分配的域,在遍历链表时,通常会依次访问它们,因此它们之间也具有紧密的关系。例如图1中,灰色方块代表的对象就满足这一种模式。同样,条纹方块代表的对象也满足这一种模式。但是灰色对象和条纹对象之间并没有紧密的关系,因为它们尽管类型相同,但是灰色对象的指针保存在节点的d1域中,而条纹对象的指针保存在节点的d2域中。
在对何种堆数据对象属于关系紧密的堆数据对象做上述定义后,在本发明中就能够识别从不同调用点分配的,但相互之间具有紧密关系的两个对象,从而将它们所属的池合并起来,使它们统一在一个池里。例如在图1中,假设虚线方块包含的节点是从另外一段程序中分配并插入链表的,由于该节点和其他节点是关系紧密的,因此,这个节点所属的池会和其它节点所属的池合并。同样,该节点的d1、d2域所指的对象所在的池也会做类似的合并。
在内存池里的对象一般是紧密排列的,当访问它们的时候会有比较好的空间局部性。这种收益只有在这些对象很多,而且对象的大小比较小的时候才比较明显。因此在实现上设置了两个门限每个内存池在开始时,把针对自己的分配请求转发给默认的分配器,直到这个池转发的分配请求超过100个(第一门限),而且这些请求分配的对象大小都小于128字节(第二门限)时,该内存池才申请一段连续的空间(段),不再把后续的分配请求转发,而是从这段空间中分配。门限1和门限2的值是可以调整的参数。在实际测试中,我们发现上述两个值比较合适。
以上是对本发明的方法如何解决前文所提到问题的相关思想的说明。下面结合图2从总体上对本发明方法的实现步骤予以说明。
步骤10)、当接收到一个分配请求后,查看当前的全局变量v,如果v中有内存池信息,则清除v的信息,然后转到步骤60),否则,执行下一步; 步骤20)、用当前调用点的地址查包装函数表,构造变长调用链。在本步骤中,通过查找包装函数表来构造变长调用链。如果当前调用点所在的包装函数在过去曾经遇到过,那么这一包装函数就会被保存在包装函数表中,因此可以直接查找包装函数表来构造变长调用链,从而达到节省开销的目的。在一个实施例中,本步骤可以具体包括以下步骤 步骤21)、初始化变长调用链为空; 步骤22)、将当前调用点的地址加入变长调用链中; 步骤23)、如果当前调用点的地址在包装函数表中,则把上一层调用点变为当前调用点,然后重新执行步骤22),否则,执行步骤30); 步骤30)、用变长调用链查映射表,如果表中有对应的内存池信息,则转到步骤60),否则执行下一步; 步骤40)、根据调用点的上下文确定它的变长调用链,并更新包装函数表。本步骤同样要构造变长调用链,但与步骤20)不同的是,采用了分析上下文语义来识别包装函数,从而构造变长调用链的方法。在前面的步骤20)中,存在当前调用地址所在的包装函数是第一次遇到的可能,此时包装函数还没有被写入到包装函数表中,因此,所得到的变长调用链可能是不准确的。这个不准确的变长调用链会在步骤30)中查映射表的时候发现(映射表中没有该变长调用链对应的项)。对于这种情况就需要执行步骤40),通过上下文的语义来识别包装函数,从而得到准确的变长调用链,并把发现的包装函数更新到包装函数表里。
在一个实施例中,该步骤包括 步骤41)、初始化这次内存分配请求的变长调用链为空; 步骤42)、将当前调用点的地址加入变长调用链中; 步骤43)、如果分配的内存对象指针没有被存到全局变量或堆中某个位置,而被当前调用点返回到上一层调用点时,把当前调用点的地址写入包装函数表中,上一层调用点变为当前调用点,然后重新执行步骤42),否则执行下一步; 步骤50)、根据生成的变长调用链确定它使用的内存池,并更新映射表;作为一种实现方式,该步骤包括 步骤51)、分析该变长调用链分配的对象的指针信息; 步骤52)、如果该变长调用链分配的对象A和另一变长调用链分配的对象B具有相同的类型,并且A的指针保存在B的某个域中,则A和B共用一个内存池,执行步骤55); 步骤53)、如果该变长调用链分配的对象A的指针记录在一组对象C的某个域里(A和C的类型可以不同),而另一变长调用链分配的对象B的指针也保存在这组对象C的同一个域里,并且A和B的类型是相同的,则A和B共用一个内存池,执行步骤55); 步骤54)、新建一个内存池; 步骤55)、将该变长调用链和内存池的对应关系写入映射表中; 步骤56)、考察变长调用链的最上层地址,如果它能确定下一次内存分配一定具有该变长调用链,则在此地址插桩修改全局变量v,记录对应的内存池信息; 步骤60)、池分配器统计该内存池的分配次数,当内存池的分配次数小于第一门限时,使用系统内存分配器进行分配;当内存池的分配次数已经达到了第一门限,则进一步判断之前分配的对象大小是否超过了第二门限,如果超过,则使用系统内存分配器进行分配,如果没有超过,则从段中分配。其中,从段中分配包括 步骤61)、当内存池的分配次数刚达到设定门限后,该内存池从系统申请一块连续的空间(段); 步骤62)、该内存池需要分配对象时,从段中分配; 步骤63)、如果当前的段使用完毕,则申请一个新段; 步骤64)、当一个段中的对象都被释放后,段被系统回收。
以上是对本发明方法的实现步骤的详细说明。本领域技术人员应当了解,关系不紧密的堆数据对象从同一个内存池分配的问题以及关系紧密的堆数据对象从不同的内存池分配的问题之间具有一定的独立性。因此,本发明的方法还可以单独解决上述两个问题中任意的一个。当本发明方法用于解决关系不紧密的堆数据对象从同一个内存池分配的问题时,可省略步骤51)-步骤53)中的相关操作。当本发明方法用于解决关系紧密的堆数据对象从不同的内存池分配的问题时,可省略步骤20)和步骤40)的操作,变长调用链直接使用长度为1的调用链(即直接调用点)。
最后所应说明的是,以上实施例仅用以说明本发明的技术方案而非限制。尽管参照实施例对本发明进行了详细说明,本领域的普通技术人员应当理解,对本发明的技术方案进行修改或者等同替换,都不脱离本发明技术方案的精神和范围,其均应涵盖在本发明的权利要求范围当中。
权利要求
1.一种在运行时对堆数据进行池分配的方法,包括
步骤1)、接收堆数据的内存池分配请求;
步骤2)、考察调用点上下文,将包含在包装函数中的所述调用点的地址和调用最上层包装函数的调用点的地址加入变长调用链;
步骤3)、为从所述变长调用链所分配的堆数据对象选择内存池;
步骤4)、从所述内存池中为所述堆数据分配空间。
2.根据权利要求1所述的在运行时对堆数据进行池分配的方法,其特征在于,所述的步骤3)包括分析变长调用链所分配的堆数据对象,为具有紧密关系的堆数据对象分配同一个内存池,为不具有紧密关系的堆数据对象分配不同的内存池。
3.根据权利要求2所述的在运行时对堆数据进行池分配的方法,其特征在于,所述的步骤3)包括
步骤3-1-1)、分析从所述变长调用链所分配的堆数据对象的指针信息;
步骤3-1-2)、从该变长调用链所分配的堆数据对象A和从另一变长调用链所分配的堆数据对象B具有相同的类型,并且所述A的指针保存在所述B的某个域中,所述A和B具有紧密关系,共用一个内存池。
4.根据权利要求2所述的在运行时对堆数据进行池分配的方法,其特征在于,所述的步骤3)包括
步骤3-2-1)、分析从所述变长调用链所分配的堆数据对象的指针信息;
步骤3-2-2)、从该变长调用链所分配的堆数据对象A的指针记录在一组对象C的某个域里,而从另一变长调用链所分配的堆数据对象B的指针也保存在这组对象C的同一个域里,并且所述A和B的类型相同,所述A和B具有紧密关系,共用一个内存池。
5.根据权利要求2所述的在运行时对堆数据进行池分配的方法,其特征在于,所述的步骤3)包括
步骤3-3-1)、分析从所述变长调用链所分配的堆数据对象的指针信息;
步骤3-3-2)、从该变长调用链所分配的堆数据对象不和从任何其它变长调用链所分配的堆数据对象共用一个内存池,新建一个内存池。
6.根据权利要求3或4或5所述的在运行时对堆数据进行池分配的方法,其特征在于,所述的步骤2)包括
步骤2-1)、用当前的调用点的地址查找包装函数表,构造变长调用链;所述包装函数表记录了已知的包装函数的信息;
步骤2-2)、用所述变长调用链查找映射表,在无法从所述映射表中找到与该变长调用链所对应的内存池的信息时,执行下一步;所述映射表保存了变长调用链与内存池之间的对应关系;
步骤2-3)、根据调用点的地址上下文确定变长调用链,并更新所述的包装函数表。
7.根据权利要求6所述的在运行时对堆数据进行池分配的方法,其特征在于,所述的步骤2-1)包括
步骤2-1-1)、初始化变长调用链为空;
步骤2-1-2)、将当前调用点的地址加入变长调用链中;
步骤2-1-3)、如果当前调用点的地址在包装函数表中,则把上一层调用点变为当前调用点,然后重新执行步骤2-1-2),否则,执行步骤2-2)。
8.根据权利要求6所述的在运行时对堆数据进行池分配的方法,其特征在于,所述的步骤2-3)包括
步骤2-3-1)、初始化这次内存分配请求的变长调用链为空;
步骤2-3-2)、将当前调用点的地址加入变长调用链中;
步骤2-3-3)、如果分配的内存对象的指针没有被存到全局变量或堆中某个位置,而被当前调用点所在的函数返回到上一层调用点时,把当前调用点的地址写入所述包装函数表中,上一层调用点变为当前调用点,然后重新执行步骤2-3-2),否则执行步骤3)。
9.根据权利要求6所述的在运行时对堆数据进行池分配的方法,其特征在于,所述的步骤3)还包括
将所述变长调用链与为该变长调用链所分配的内存池之间的对应关系更新到所述映射表中。
10.根据权利要求1或2或3或4或5或6所述的在运行时对堆数据进行池分配的方法,其特征在于,所述的步骤4)包括
步骤4-1)、池分配器统计所述内存池的分配次数;
步骤4-2)、当内存池的分配次数小于第一门限时,使用系统内存分配器进行分配,否则,执行下一步;
步骤4-3)、内存池的分配次数已经达到了第一门限,进一步判断之前分配的对象大小是否超过了第二门限,当超过时,使用系统内存分配器进行分配,当没有超过时,从段中分配。
11.根据权利要求10所述的在运行时对堆数据进行池分配的方法,其特征在于,所述的从段中分配包括
步骤4-3-1)、当内存池的分配次数刚达到设定门限后,该内存池从系统申请一块段;
步骤4-3-2)、该内存池需要分配对象时,从段中分配;
步骤4-3-3)、如果当前的段使用完毕,则申请一个新段;
步骤4-3-4)、当一个段中的对象都被释放后,段被系统回收。
全文摘要
本发明提供一种在运行时对堆数据进行池分配的方法,包括接收堆数据的内存池分配请求;考察调用点上下文,将包含在包装函数中的所述调用点的地址和调用最上层包装函数的调用点的地址加入变长调用链;为从所述变长调用链所分配的堆数据对象选择内存池;从所述内存池中为所述堆数据分配空间。本发明能够解决关系不紧密的堆数据对象因为在同一个调用点分配而从同一个内存池分配的问题以及关系紧密的堆数据对象因为在不同的调用点分配而从不同的内存池分配的问题,提高了池分配的效果。
文档编号G06F12/02GK101763308SQ20091024391
公开日2010年6月30日 申请日期2009年12月25日 优先权日2009年12月25日
发明者王振江, 武成岗 申请人:中国科学院计算技术研究所