pyhton内存管理
变量的存储
只有Python解释器运行了pyhton文件,字符被读入了内存,才会有变量这个概念。也就是说变量是存放在内存当中的
变量名:存储在名称空间中,存储了变量值的内存地址,调用变量名,即通过内存地址访问变量值
变量值:存储在内存中
引用计数
每当定义一个变量,即开辟一个内存空间存放变量值
同时往名称空间中添加变量名,存放变量值的内存地址
变量名就是变量值的一个引用
x = 10 # 10引用计数加1为1
y = x # 10引用计数加1为2
x = 11 # 10引用计数减1为1;11引用计数加1为1
del y # 10引用计数减1为0,触发python垃圾回收机制,python清理10的内存占用
python垃圾回收机制
存储机制:
栈区:存储变量名和变量值内存地址关联关系
堆区:存储变量值
内存管理回收的是堆区的内容
1、引用计数
变量值引用计数为0,变量值所占的内存会被释放
2、标记清除
循环引用:
1、容器对象包含其他对象,存储的只是其他对象的内存地址,添加引用而已
2、循环引用指的就是容器对象互相包含,即互相引用了,那么当栈区变量名与内存关联被删除后,它们的值存储了对方的引用,即引用计数不为0,然后又跟其他的任何对象不产生关联。
3、容器对象,如列表,字典,元组,集合,类等都可以包含其他对象的引用,都可能产生循环引用问题
标记清除:
1、使用GC算法
2、标记:遍历所有的GC Roots对象(栈区中的所有内容或者线程),将所有GC Roots对象能直接或者间接访问到的d对象标记为存活状态,其余的均为非存活状态,应该被清除
3、清除:遍历堆中所有的对象,将没有标记的对象全部清除
2、分代回收
背景:基于引用计数的回收机制,每次回收内存,都需要把所有对象的引用计数都遍历一遍,非常耗时
分代:指的是根据变量在多次扫描后,都没有被回收的变量,gc机制将其扫描频率降低,这样多次分级之后,大大减少了遍历的变量个数,节省了时间
回收:依然是,引用计数为0就回收内存
小整数池
Python实现int的时候有个小整数池。
为了避免因创建相同的值而重复申请内存空间所带来的效率问题, Python解释器会在启动时创建出小整数池,范围是[-5,256]
该范围内的小整数对象是全局解释器范围内被重复使用,永远不会被垃圾回收机制回收
另外
在pycharm中运行python程序时
pycharm出于对性能的考虑,会扩大小整数池的范围,其他的字符串等不可变类型也都包含在内
这是一种优化机制,至于范围到底多大,无需细究