您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 其它行业文档 > ART运行时CompactingGC为新创建对象分配内存的过程分析
ART运行时CompactingGC为新创建对象分配内存的过程分析在引进CompactingGC后,ART运行时优化了堆内存分配过程。最显著特点是为每个ART运行时线程增加局部分配缓冲区(TheadLocalAllocationBuffer)和在OOM前进行一次同构空间压缩(HomogeneousSpaceCompact)。前者可提高堆内存分配效率,后者可解决内存碎片问题。本文就对ART运行时引进CompactingGC后的堆内存分配过程进行分析。从接口层面上看,除了提供常规的对象分配接口AllocObject,ART运行时的堆还提供了一个专门用于分配非移动对象的接口AllocNonMovableObject,如图1所示:非移动对象指的是保存在前面一篇文章提到的Non-MovingSpace的对象,主要包括那些在类加载过程中创建的类对象(Class)、类方法对象(ArtMethod)和类成员变量对象(ArtField)等,以及那些在经历过若干次GenerationalSemi-SpaceGC之后仍然存活的对象。前者是通过AllocNonMovableObject接口分配的,而后者是在执行GenerationalSemi-SpaceGC过程移动过去的。本文主要关注通过AllocNonMovableObject接口分配的非移动对象。无论是通过AllocObject接口分配对象,还是通过AllocNonMovableObject接口分配对象,最后都统一调用了另外一个接口AllocObjectWithAllocator进行具体的分配过程,如下所示:[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片classHeap{public:......//Allocatesandinitializesstorageforanobjectinstance.templateboolkInstrumented,typenamePreFenceVisitormirror::Object*AllocObject(Thread*self,mirror::Class*klass,size_tnum_bytes,constPreFenceVisitor&pre_fence_visitor)SHARED_LOCKS_REQUIRED(Locks::mutator_lock_){returnAllocObjectWithAllocatorkInstrumented,true(self,klass,num_bytes,GetCurrentAllocator(),pre_fence_visitor);}templateboolkInstrumented,typenamePreFenceVisitormirror::Object*AllocNonMovableObject(Thread*self,mirror::Class*klass,size_tnum_bytes,constPreFenceVisitor&pre_fence_visitor)SHARED_LOCKS_REQUIRED(Locks::mutator_lock_){returnAllocObjectWithAllocatorkInstrumented,true(self,klass,num_bytes,GetCurrentNonMovingAllocator(),pre_fence_visitor);}templateboolkInstrumented,boolkCheckLargeObject,typenamePreFenceVisitorALWAYS_INLINEmirror::Object*AllocObjectWithAllocator(Thread*self,mirror::Class*klass,size_tbyte_count,AllocatorTypeallocator,constPreFenceVisitor&pre_fence_visitor)SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);AllocatorTypeGetCurrentAllocator()const{returncurrent_allocator_;}AllocatorTypeGetCurrentNonMovingAllocator()const{returncurrent_non_moving_allocator_;}......private:......//Allocatortype.AllocatorTypecurrent_allocator_;constAllocatorTypecurrent_non_moving_allocator_;......};这五个函数定义在文件art/runtime/gc/heap.h在Heap类的成员函数AllocObject和AllocNonMovableObject中,参数self描述的是当前线程,klass描述的是要分配的对象所属的类型,参数num_bytes描述的是要分配的对象的大小,最后一个参数pre_fence_visitor是一个回调函数,用来在分配对象完成后在当前执行路径中执行初始化操作,例如分配完成一个数组对象,通过该回调函数立即设置数组的大小,这样就可以保证数组对象的完整性和一致性,避免多线程环境下通过加锁来完成相同的操作。Heap类的成员函数AllocObjectWithAllocator需要另外一个额外的类型为AllocatorType的参数来描述分配器的类型,也就是描述要在哪个空间分配对象。AllocatorType是一个枚举类型,它的定义如下所示:[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片//Differenttypesofallocators.enumAllocatorType{kAllocatorTypeBumpPointer,//UseBumpPointerallocator,hasentrypoints.kAllocatorTypeTLAB,//UseTLABallocator,hasentrypoints.kAllocatorTypeRosAlloc,//UseRosAllocallocator,hasentrypoints.kAllocatorTypeDlMalloc,//Usedlmallocallocator,hasentrypoints.kAllocatorTypeNonMoving,//Specialallocatorfornonmovingobjects,doesn'thaveentrypoints.kAllocatorTypeLOS,//Largeobjectspace,alsodoesn'thaveentrypoints.};这个枚举类型定义在文件/art/runtime/gc/allocator_type.h。AllocatorType一共有六个值,它们的含义如下所示:kAllocatorTypeBumpPointer:表示在BumpPointerSpace中分配对象。kAllocatorTypeTLAB:表示要在由BumpPointerSpace提供的线程局部分配缓冲区中分配对象。kAllocatorTypeRosAlloc:表示要在RosAllocSpace分配对象。kAllocatorTypeDlMalloc:表示要在DlMallocSpace分配对象。kAllocatorTypeNonMoving:表示要在NonMovingSpace分配对象。kAllocatorTypeLOS:表示要在LargeObjectSpace分配对象。Heap类的成员函数AllocObject和AllocNonMovableObject使用的分配器类型分别是由成员变量current_allocator_和current_non_moving_allocator_决定的。前者的值与当前使用的GC类型有关。当GC类型发生变化时,就会调用Heap类的成员函数ChangeCollector来修改当前使用的GC,同时也会调用另外一个成员函数ChangeAllocator来修改Heap类的成员变量current_allocator_的值。由于ART运行时只有一个Non-MovingSpace,因此后者的值就固定为kAllocatorTypeNonMoving。Heap类的成员函数ChangeCollector的实现如下所示:[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片voidHeap::ChangeCollector(CollectorTypecollector_type){//TODO:Onlydothiswithallmutatorssuspendedtoavoidraces.if(collector_type!=collector_type_){......collector_type_=collector_type;gc_plan_.clear();switch(collector_type_){casekCollectorTypeCC://Fall-through.casekCollectorTypeMC://Fall-through.casekCollectorTypeSS://Fall-through.casekCollectorTypeGSS:{gc_plan_.push_back(collector::kGcTypeFull);if(use_tlab_){ChangeAllocator(kAllocatorTypeTLAB);}else{ChangeAllocator(kAllocatorTypeBumpPointer);}break;}casekCollectorTypeMS:{gc_plan_.push_back(collector::kGcTypeSticky);gc_plan_.push_back(collector::kGcTypePartial);gc_plan_.push_back(collector::kGcTypeFull);ChangeAllocator(kUseRosAlloc?kAllocatorTypeRosAlloc:kAllocatorTypeDlMalloc);break;}casekCollectorTypeCMS:{gc_plan_.push_back(collector::kGcTypeSticky);gc_plan_.push_back(collector::kGcTypePartial);gc_plan_.push_back(collector::kGcTypeFull);ChangeAllocator(kUseRosAlloc?kAllocatorTypeRosAlloc:kAllocatorTypeDlMalloc);break;}default:{LOG(FATAL)Unimplemented;}}......}}这个函数定义在文件ime/gc/heap.cc中。从这里我们就可以看到,对于CompactingGC,它们使用的分配器类型只可能为kAllocatorTypeTLAB或者kAllocatorTypeBumpPointer,取决定Heap类的成员变量use_tlab_的值。Heap类的成员变量use_tlab_的值默认为false,但是可以通过ART运行时启动选项-XX:UseTLAB来设置为true。对于Mark-SweepGC来说,它们使用的分配器类型只可能为kAllocatorTypeRosAlloc或者kAllocatorTypeDlMalloc,取决于常量kUseRosAlloc的值。此外,我们还可以看到,根据当前使用的GC不同,Heap类的成员变量gc_plan_会被设置为不同的值,用来表示在分配对
本文标题:ART运行时CompactingGC为新创建对象分配内存的过程分析
链接地址:https://www.777doc.com/doc-23767 .html