python内存管理

python内存管理

引用计数

python引用机制

python动态类型–》引用和对象分离

对象是存储在内存中的实体

对象–》一种数据结构–》存储对象类型、对象数值、引用计数(计算对象被引用了几次,在哪些地方被引用了)

引用计数的作用

统计有哪些变量引用指向了当前对象

当有新的引用指向的时候,引用计数+1

当有无效的引用发生的时候,引用计数-1

当对象的引用计数为0的时候,会被销毁

getrefcount能够获取对象的引用计数(比实际值多一)

>>> from sys import getrefcount
>>> a=500
>>> getrefcount(a)
2

此处500的引用计数为2,是因为getrefcount会创建一个临时的引用指向500这个对象,当getrefcount执行完以后就会自动删掉这个临时的引用

>>> b=a
>>> getrefcount(a)
3
>>> lst=[a]  #列表为可变数据类型放的都是引用
>>> getrefcount(a)
4

del–删除变量的引用

>>> del a
>>> getrefcount(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> getrefcount(b)
3

引用计数的弊端:引用计数可以解决大部分内存释放问题,但是无法解决循环引用问题

>>> x=[1]
>>> y=[2]
>>> x.append(y)
>>> getrefcount(y)
3
>>> y.append(x)
>>> getrefcount(x)
3
>>> x
[1, [2, [...]]]
>>> y
[2, [1, [...]]]
>>> del x
>>> del y
>>> x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>> y
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'y' is not defined

删除x,y引用计数都减1,但是没有归0,在内存中就不会释放,程序又不能访问这片空间,造成内存泄露。使用其他的内存管理模式-------垃圾回收

垃圾回收

回收原则

​ 当python的某个对象的引用计数降为0时,可以被垃圾回收

gc机制

​ GC--------现代编程语言的自动内存管理机制。

​ 作用------找到内存中无用的垃圾资源

​ 清除这些垃圾并把内存让出来给其他对象使用。

效率问题

​ 垃圾回收时,python不能进行其他的任务。频繁的垃圾回收会大大降低python的工作效率

>>> import gc
>>> gc.get_threshold()
(700, 10, 10)
>>> gc.collect()
2

​ 700表明当垃圾回收的分配对象和取消分配对象(del、a=b)的差值达到700时,垃圾回收机制才会启动。

三种情况触发垃圾回收

​ 1.调用gc.collect()

​ 2.GC达到阈值时

​ 3.程序退出时

引用计数无法解决循环引用的问题那就使用垃圾回收处理

垃圾回收: 1、找到垃圾 2、回收垃圾

1、找垃圾 ---- 分代回收

2、清除垃圾 ---- 标记清除 ---- 清除循环引用的垃圾

分代回收

存活时间越久的对象,越不可能成为垃圾。

分代回收一共有三代成员:

1,2,3,4,5,6,7,8,9---------------新建对象 : 0代成员

​ 每一次垃圾回收的时候,都会被检查

3,4,5,6---------------1代长老

​ 在0代成员被扫描10次垃圾回收后,依然存活-----1代长老

​ 0代扫描10次,才会扫描一次1代成员

5,6-------------------2代长老

​ 当1代成员被扫面10次依然存活就会被标注为2代成员

​ 1代扫描10次以后才会扫描一次2代

标记清除

标记对象,清除垃圾

主要用于解决循环引用

1.标记:活动(有被引用),非活动(可被删除)

2.清除:清除所有非活动的对象

内存泄漏:(占着茅坑不拉屎) 有一部分内存无法被释放,进程又无法访问

内存溢出OOM:(out of memory) 内存不够用,程序需要的内存大于系统空闲内存

内存池机制

整数对象缓存池:
>>> a=1
>>> b=2
>>> from sys import getrefcount
>>> getrefcount(a)
801
>>> getrefcount(b)
101
>>> c=200
>>> getrefcount(c)
3
>>> d=500
>>> f=500
>>> getrefcount(d)
2
>>> getrefcount(f)
2
>>> g=1
>>> getrefcount(g)
802
>>> h=1
>>> getrefcount(h)
803
>>> id(g)
139685766129568
>>> id(h)
139685766129568
>>> id(f)
139685766788080
>>> id(d)
139685766788112

a=1、g=1、h=1指向同一个1

d=500、f=500指向不同的500

原因:内存池机制,小整型数会有一个小整数池(-5~256)

当解释器运行起来以后会在内存空间里面开辟一段空间作为一个小整数池

当创建对象时会先看对象的数值在不在小整数池里,如果在就直接指向内存池对于的空间,否则单独开辟一段空间让对象指向这段空间。

字符串驻留区:

内存开辟一段空间用作字符串驻留区,当定义一个字符串时,先看字符串驻留区里是否已经存在。如果存在则直接引用指向,不存在则创建然后添加到驻留区。

>>> str1="abc"
>>> str2="abc"
>>> id(str1)
139685767591224
>>> id(str2)
139685767591224
>>> str1 is str2
True

字符串中如果有特殊字符则不会放到驻留区。单个特殊字符可以放到驻留区

>>> str1="abc "
>>> str2="abc "
>>> id(str1)
139685766975360
>>> id(str2)
139685767008584
>>> str1="$"
>>> str2="$"
>>> id(str1)
139685767256304
>>> id(str2)
139685767256304

总结

python内存管理------引用计数为主,分代回收和标记清除为辅的垃圾回收方式进行内存回收管理,还引用了小整型缓冲池以及常用字符串驻留区的方式进行内存管理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值