python的内存管理机制有什么呢?(总纲)
- 引用计数
- 垃圾回收
- 内存池
1. 引用计数
- 概念:
引用计数是一种非常高效的内存管理手段,python内部就是使用引用计数,来保持追踪内存中的对象,python内部记录了对象有多少个引用。当一个python对象被引用时其引用计数增加1,当其不再被一个变量引用时则计数减1,当引用计数为0时对象被删除。 - 什么情况下引用计数增加1:
- 对象被创建
a = 23 - 对象被引用
a = 23345455 b = a - 对象被作为参数,传入到一个函数中;
增加了一个引用
a = 23345455
增加了一个引用
b = a
增加了一个引用
c = b
增加了一个引用
print(sys.getrefcount(b)) # 执行完毕后引用销毁,减少一个引用
增加了一个引用
print(sys.getrefcount©) - 对象作为一个元素,存储在容器中;
a = 23345455
b = a
list = [a, b] # 增加了2个引用
print(sys.getrefcount(b)
原文链接:
- 什么情况下引用计数减1:
- 对象的别名被赋予新的对象
a = 23345455 # 增加了一个引用
b = a # 增加了一个引用
print(sys.getrefcount(a))
b = 1.4 # 减少了一个23345455整数的引用
print(sys.getrefcount(a))
- 对象的别名被销毁
a = 23345455 # 增加了一个引用
b = a # 增加了一个引用
list = [a, b] # 增加了2个引用
del a
print(sys.getrefcount(b))
- 一个对象离开他的作用域
a = 23345455 # 增加了一个引用
b = a # 增加了一个引用
print(sys.getrefcount(a)) # 执行完毕后引用销毁
print(sys.getrefcount(a))
- 对象所在的容器被销毁,或从容器中删除对象
# 增加了一个引用
a = 23345455
# 增加了一个引用
b = a
list = [a, b] # 增加了2个引用
del list
print(sys.getrefcount(b))
2. 垃圾回收
**在python中,垃圾回收机制主要是以引用计数为主要手段,以标记清除和分代回收机制作为辅助手段实现的**
- 引用计数
1. 引用计数也是一种垃圾回收机制,而且是最直观最简单的垃圾回收机制,当python的某个对象的引用降为0时,说明没有任何引用指向该对象,该对象就成了垃圾。当然除了引用计数为0的会被清除,还有一种情况也会被垃圾回收机制清除掉,当两个对象互相引用时,他们本身其他的引用已经为0了。
2. 垃圾回收机制还有一个循环垃圾回收器,确保释放的引用对象(a引用b,b引用a,导致其引用计数永远不为0) - 标记清除
标记清除算法是一种基于追踪回收(tracing GC)技术实现的垃圾回收算法。它分为两个阶段:第一阶段是标记阶段 GC会把所有的活动对象打上标记,第二阶段是把那些没有标记的对象非活动对象进行回收。
标记清除算法作为python的辅助垃圾收集技术,主要处理的是一些容器对象,比如list,dict,tuple等,因为对于字符串,数值对象是不可能造成循环引用问题。python使用一个双向链表讲这些容器对象组织起来。不过,这种简单粗暴的标记清除算法也是有明显的缺点,清除非活动的对象前他必须顺序扫描整个堆内存,哪怕只剩下小部分活动对象也要扫描所有对象。 - 分代回收
分代回收的整体思想是:将系统中的所有内存块根据其存活时间划分为不同的集合,每个集合就成为一个‘代’,垃圾收集频率随着‘代’的存活时间的增大而减小,存活时间通常利用几次垃圾回收来度量。
python默认定义了三代对象集合,索引数越大,对象存活时间越长。
3. 内存池机制(这部分我也不太熟,想好了在写)
先解说一下什么叫池,池就是先开辟好一个空间,提高代码的运行效率,不会在运行的时候才拿到内存。
python提供了对内存的垃圾收集机制,但是他讲不用的内存放到内存池而不是返回给操作系统。
python中有分为大内存和小内存:(256k为界限分大小内存)
1. 大内存中使用malloc进行分配
2. 小内存使用内存池进行分配
3. python的内存池(金字塔)
第0层:
大内存-----若请求分配的内存大于256k,malloc函数分配内存,free函数释放内存
第1,2层:操作系统进行操作
第3层:是最上层,也就是我们对python对象的直接操作。