MicroPython GC模块原理

  • Post author:
  • Post category:python





一、 回收算法

GC模块的回收算法只用到了标记清除算法(make-sweep),通过标记的方法将内存分为free和mark状态,每次调用回收函数时会将未mark的区域回收。当内存使用达到阈值或者主动调用GC.collect()会进行垃圾回收。




二、 内存分布

被管理的内存空间分为三部分,分别是alloc table(ATB)、finaliser table(FTB)、和pool(详细算法见gc_init函数)。

分配的最小单位为block,块的大小通过BYTES_PER_BLOCK设置。

alloc table:用来记录每个block的状态,状态分为mark、free、head、tail四种,用两个bit表示状态。

Finalizer table:用来记录block是否使用finaliser(__del__方法),用一个bit表示。

Pool: 用户使用的空间。

在这里插入图片描述




三、 标记回收过程

内存可以分为四种标记状态:mark、free、head、tail

Micropython的GC回收主要使用两个函数gc_collect_root、gc_sweep

gc_collect_root主要遍历栈中正在使用的gc内存,并将其mark防止被释放,之后再调用gc_sweep进行回收,将所有未标记的内存 (head和tail),gc_sweep会遍历所有block将未标记的内存进行回收释放(标记为free状态),已经标记的块再次置为未标记状态(),用于下次回收,这样就形成了垃圾回收的循环。

MicroPython中GC模块的源码:

void gc_collect(void) {
	//标记虚拟机中的区域,防止内存被踩踏
    gc_collect_start();

#if MICROPY_PY_THREAD
    // trace root pointers from any threads
    //多线程模式标记每个线程的内存
    mp_thread_gc_others();
#else
	//单线程模式标记当前线程的内存
	gc_collect_root(rt_thread_self()->sp, ((mp_uint_t)((void *)MP_STATE_THREAD(stack_top) - rt_thread_self()->sp)) / 4);
#endif
	//将未标记的内存进行统一回收
    gc_collect_end();
    gc_dump_info();
}

在这里插入图片描述

在这里插入图片描述



四、 Micropython GC模块缺陷

相对于cpython和java等高级语言的垃圾回收机制,缺少分代算法、引用计数算法、复制算法等方式提高稳定性和回收效率。



版权声明:本文为u012441962原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。