美文网首页
Python是如何实现内存管理的?

Python是如何实现内存管理的?

作者: 阳光小镇少爷 | 来源:发表于2024-09-22 17:44 被阅读0次

点评:当面试官问到这个问题的时候,一个展示自己的机会就摆在面前了。你要先反问面试官:“你说的是官方的CPython解释器吗?”。这个反问可以展示出你了解过Python解释器的不同的实现版本,而且你也知道面试官想问的是CPython。当然,很多面试官对不同的Python解释器底层实现到底有什么差别也没有概念。所以,千万不要觉得面试官一定比你强,怀揣着这份自信可以让你更好的完成面试。

Python提供了自动化的内存管理,也就是说内存空间的分配与释放都是由Python解释器在运行时自动进行的,自动管理内存功能极大的减轻程序员的工作负担,也能够帮助程序员在一定程度上解决内存泄露的问题。以CPython解释器为例,它的内存管理有三个关键点:引用计数、标记清理、分代收集。

引用计数:对于CPython解释器来说,Python中的每一个对象其实就是PyObject结构体,它的内部有一个名为ob_refcnt 的引用计数器成员变量。程序在运行的过程中ob_refcnt的值会被更新并藉此来反映引用有多少个变量引用到该对象。当对象的引用计数值为0时,它的内存就会被释放掉。

typedef struct _object {
_PyObject_HEAD_EXTRA
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
} PyObject;

以下情况会导致引用计数加1:
对象被创建
对象被引用
对象作为参数传入到一个函数中
对象作为元素存储到一个容器中

以下情况会导致引用计数减1:
用del语句显示删除对象引用
对象引用被重新赋值其他对象
一个对象离开它所在的作用域
持有该对象的容器自身被销毁
持有该对象的容器删除该对象

可以通过sys模块的getrefcount函数来获得对象的引用计数。引用计数的内存管理方式在遇到循环引用的时候就会出现致命伤,因此需要其他的垃圾回收算法对其进行补充。

标记清理:CPython使用了“标记-清理”(Mark and Sweep)算法解决容器类型可能产生的循环引用问题。
该算法在垃圾回收时分为两个阶段:标记阶段,遍历所有的对象,如果对象是可达的(被其他对象引用),那么就标记该对象为可达;清除阶段,再次遍历对象,如果发现某个对象没有标记为可达,则就将其回收。
CPython底层维护了两个双端链表,一个链表存放着需要被扫描的容器对象(姑且称之为链表A),另一个链表存放着临时不可达对象(姑且称之为链表B)。为了实现“标记-清理”算法,链表中的每个节点除了有记录当前引用计数的ref_count变量外,还有一个gc_ref变量,这个gc_ref是ref_count的一个副本,所以初始值为ref_count的大小。执行垃圾回收时,首先遍历链表A中的节点,并且将当前对象所引用的所有对象的gc_ref减1,这一步主要作用是解除循环引用对引用计数的影响。再次遍历链表A中的节点,如果节点的gc_ref值为0,那么这个对象就被标记为“暂时不可达”(GC_TENTATIVELY_UNREACHABLE)并被移动到链表B中;如果节点的gc_ref不为0,那么这个对象就会被标记为“可达“(GC_REACHABLE),对于”可达“对象,还要递归的将该节点可以到达的节点标记为”可达“;链表B中被标记为”可达“的节点要重新放回到链表A中。在两次遍历之后,链表B中的节点就是需要释放内存的节点。

分代回收:在循环引用对象的回收中,整个应用程序会被暂停,为了减少应用程序暂停的时间,Python 通过分代回收(空间换时间)的方法提高垃圾回收效率。分代回收的基本思想是:对象存在的时间越长,是垃圾的可能性就越小,应该尽量不对这样的对象进行垃圾回收。CPython将对象分为三种世代分别记为0、1、2,每一个新生对象都在第0代中,如果该对象在一轮垃圾回收扫描中存活下来,那么它将被移到第1代中,存在于第1代的对象将较少的被垃圾回收扫描到;如果在对第1代进行垃圾回收扫描时,这个对象又存活下来,那么它将被移至第2代中,在那里它被垃圾回收扫描的次数将会更少。分代回收扫描的门限值可以通过gc模块的get_threshold函数来获得,该函数返回一个三元组,分别表示多少次内存分配操作后会执行0代垃圾回收,多少次0代垃圾回收后会执行1代垃圾回收,多少次1代垃圾回收后会执行2代垃圾回收。需要说明的是,如果执行一次2代垃圾回收,那么比它年轻的代都要执行垃圾回收。如果想修改这几个门限值,可以通过gc模块的set_threshold函数来做到。

相关文章

  • 新手上路?八大秘术助你offer无数(Python初学者/码农必

    话不多说,干货: 1、Python是如何进行内存管理的? Python的内存管理主要有三种机制:引用计数机制、垃圾...

  • 深入理解Python内存管理与垃圾回收,再也不怕问了(一)

    面试官:听说你学Python?那你给我讲讲Python如何进行内存管理? 我:???内存管理不太清楚额。。。 面试...

  • Python内存管理

    引用于 https://zhuanlan.zhihu.com/p/113019698 Python是如何管理内存的...

  • python爬虫面试题

    python是如何进行内存管理的? a、对象的引用计数机制 python内部使用引用计数,来保持追踪内存中的对象,...

  • python基础1

    一·Python是如何进行内存管理Python是动态类型的语言,对象与引用分离,在Python中,整数和短小的字符...

  • python学习一

    1 python 如何管理内存 对象引用计数机制,垃圾回收机制,内存池机制 一。对象引用机制 python内部引用...

  • python是如何管理内存的?

    python 是一门动态类型的面向对象的编程语言,它把所有的对象和数据结构都保存在私有堆空间中。python通过内...

  • InterV For Python

    0x01 Python是如何进行内存管理的 引用计数Python使用引用计数来保持追踪内存中的对象,所有对象都有...

  • linux内核

    虚拟内存的作用? 虚拟内存的实现? 操作系统层面对内存的管理? 内存池的作用?STL里[内存池如何实现] 进程空间...

  • Python内存管理知识点讲解(广州中软卓越)

    在学习广州中软卓越python培训课程中,我们会遇到一些关于python的问题,比如Python是如何进行内存管理...

网友评论

      本文标题:Python是如何实现内存管理的?

      本文链接:https://www.haomeiwen.com/subject/kzfqedtx.html