python中创建的对象的时候,首先会去申请内存地址,然后对对象进行初始化,所有对象都会维护在一个叫做refchain的双向循环链表中,每个数据都保存如下信息
- 链表中数据前后数据的指针
- 数据的类型
- 数据值
- 数据的引用计数
- 数据的长度(list,dict..)
一、引用计数机制
引用计数增加:
- 对象被创建
- 对象被别的变量引用(另外起了个名字)
- 对象被作为元素,放在容器中(比如被当作元素放在列表中)
- 对象被当成参数传递到函数中
引用计数减少:
- 对象的别名被显式的销毁
- 对象的一个别名被赋值给其他对象 (例:比如原来的a=10,被改成a=100,那么此时10的引用计数
- 就减少了)
- 对象从容器中被移除,或者容器被销毁(例:对象从列表中被移除,或者列表被销毁)
- 一个引用离开了它的作用域(调用函数的时候传进去的参数,在函数运行结束后,该参数的引用即
- 被销毁)
查看引用计数
import sys
sys.getrefcount(obj)
二、数据池和缓存
1、小整数池
Python自动将-5~256的整数进行了缓存到一个小整数池中,当你将这些整数赋值给变量时,并不会重新创建对象,而是使用已经创建好的缓存对象,当删除这些数据的引用时,也不会进行回收。
2、intern机制
intern机制,也称为字符串驻留池,是针对于字符串内存管理的一种优化处理的机制。
intern机制的优点是,在创建新的字符串对象时,会先在缓存池里面找是否有已经存在的值相同的对象(标识符,即只包含数字、字母、下划线的字符串),如果有,则直接拿过来用(引用),避免频繁的创建和销毁内存,提升效率。
3、缓存机制
- float缓存100个对象
- dict、list等一些内置的数据类型,会缓存80个对象
- 元组 会根据元组数据的长度,分别缓存元组长度为0-20的对象。
- 其他的类型缓存2个对象
三、标记清除:
引用计数存在一个缺点:那就是当两个对象出现循环引用的时候,那么这个两个变量始终不会被销毁,这样就会导致内存泄漏。
标记清除就是为了解决上述循环引用的情况
四、分代回收
gc.get_threshold:获取分代回收的频率
- 返回的是(700,10,10),这也是gc的默认值。这个值的意思是说,在第0代对象数量达到700个
- 之前,不把未被回收的对象放入第一代;而在第一代对象数量达到10个之前也不把未被回收
- 的对象移到第二代
- gc.set_threshold: 设置分代回收的频率