python的垃圾回收机制

 1.计算机中将内存分为3部分,一部分是堆,一部分是栈,还有静态存储区。

  • 静态存储区:存放全局变量,静态变量,由系统自动开辟内存,自动回收,生存周期为整个程序
  • 栈一般存放局部变量,形参等,由系统自动开辟空间,自动回收。其生存周期为块内,地址为由高到低分配
  • 堆一般是由程序员自己申请,自己回收,如果忘记回收就会一直占用内存,电脑速度就会变慢。且不断的malloc不回收的话会导致内存碎片话,可用的空间越来越少。用专业的词汇就叫内存泄露。

       堆一般是由程序员自己申请,自己回收,如果忘记回收就会一直占用内存,电脑速度就会变慢。且不断的malloc不回收的话会导致内存碎片话,可用的空间越来越少。用专业的词汇就叫内存泄露。                       

     2.不同的语言都有一定额机制来解决,今天就来看看python是如何解决的。

  1. 首先先来看下2个重要的结构体PyObject()和PyVarObject()
    1.typedef struct _object {
    2._PyObject_HEAD_EXTRA // 用于构造双向链表
    3.Py_ssize_t ob_refcnt; // 引用计数器
    4.struct _typeobject *ob_type; // 数据类型
    5.} PyObject;
    1.typedef struct {
    2.PyObject ob_base; // PyObject对象
    3.Py_ssize_t ob_size; /* Number of items in variable part,即:元素个数 */
    4.} PyVarObject;

     

    第一个结构有先驱,后继指针,引用计数器,数据类型4个基本结构,int,float,string等类型都是基于该结构体,而list,tuple,dir,set由多个元素的结构体都是基于第二个结构体。了解了基本的结构体,我们在来聊聊python是如何创建变量的,python底层由4条链表,这4张链表解决了垃圾回收的所有问题。

 

               了解了基本的结构体,我们在来聊聊python是如何创建变量的,python底层由4条链表,这4张链表解决了垃圾回收的所有问题。第一张表:双线循环链表。,每创建一个新的变量,都会将其放到该链表中。同时,引用计数器refcnt加一。每引用一次,计数器就会加一。 

import os
import sys
a=12
b=a
print(sys.getrefcount(12))
c=b
print(sys.getrefcount(12))
print(id(a),id(b))

 

 

      1.计数器回收机制

            每引用一次计数器加1,每del一个,计数器减一,当计数器为0时,变成垃圾被回收。

      2.标记回收机制

            计数器回收机制存在一个bug,当有循环引用时变会成为永久垃圾例如:

l1=[1,2,3]
l2=[2,3,4]
l1.append((l2))
l2.append((l1))
del l1
del l2

          当d1,d2被删除时,便失去了对列表的调用,但列表的引用又不为0不会被当作垃圾回收,所以变成了永久垃圾。为了解决这一问题,出现了标记清除。另外开辟一个特殊链表,专门用于存放可能存在循环引用的对象,例如list,tuple,set,dir.每隔一段时间就扫描一次链表。发现循环引用就将双方的引用标记变为-1.

   

3.分代清除

          这是在标记清除的链表分了3个链表,0代,1代,2代。每新建一个对象将其加入到链表中,当链表满700次时进行扫描,但通常会查看1代是否达到阈值,没有达到阈值扫描0代,将循环引用删除。当1代达到阈值会扫描2代,2代如果也达到阈值,进行全盘扫描,并将计数器归0.

            

     上面4条链表解决了python关于垃圾回收的所有问题。当然,为了提高效率,python也有一定的缓存机制。

  1. 常量池:-5~257.

    定义一个常量时,会先检查是否在常量池内,如果在,直接引用,超出范围在新建一个对象

     2.Float

    Python有一个free_list来存放float,大约有80个,当计数器为0时,不会直接清除,而是放入到链表中,下次在创建新对象时,不在开辟新的空间,直接从选取表中的一个对象对其重新赋值。

     3.Tuple

     List,set,dir都与float大同小异。Tuple则不同,其free_list有20个,每个存放的并不是值,而是个数,第一个存放长度为0的元组个数,第2个存放长度为1的元组个数,以此类推,第20个存放长度为0 的元组。每个都可以存放2000

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值