Python是如何进行内存管理的?(图文讲解)

这篇具有很好参考价值的文章主要介绍了Python是如何进行内存管理的?(图文讲解)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

2022-10-10更新了内容


Python是如何进行内存管理的?(图文讲解)

python采用的是引用计数机制为主,标记-清除和分代收集(隔代回收)两种机制为辅的策略

一、对象的引用计数机制

引用计数是一种垃圾回收机制,而且也是一种最直观、最简单的垃圾回收机制。当python的某个对象的引用计数为0时,该对象就成为要被回收的垃圾了。但是并不是立马就回收,等到gc触发的时候才开始回收。不过如果出现循环引用的话,引用计数机制就不再起有效的作用了。
Python是如何进行内存管理的?(图文讲解)

一个变量指向了内存地址,引用计数为1
两个变量同时指向了一个内存地址,引用计数为2

Python是如何进行内存管理的?(图文讲解)

为什么引用计数为2呢?
🔥🔥🔥注意:

查看一个对象的引用计数: sys.getrefcount() 总是会比实际+1 ,因为 sys.getrefcount() 也调用了它一次 .但是print(sys.getrefcount(b))在执行完毕后引用就删除了。

Python内部使用引用计数,来保持追踪内存中的对象,所有对象都有引用计数。

1、引用计数增加的情况:

a、一个对象分配一个新名称

a=4553223

b、将其放入一个容器中(如列表、元组或字典)

a=4553223
b=a
c=[a]
c.append(a)
print(sys.getrefcount(a))

2、引用计数减少的情况:

a、使用del语句删除引用

del a

b、引用超出作用域或被重新赋值

def test():
    b=667787
test()

函数执行完函数中的引用计数为0,可以进行回收

二、垃圾回收

1、当一个对象的引用计数归零时,它将被垃圾回收机制处理掉。
2、当两个对象a和b相互引用时,del语句可以减少a和b的引用计数,并销毁用于引用底层对象的名称。然而由于每个对象都包含一个对其他对象的应用,因此引用计数不会归零,对象也不会销毁。(从而导致内存泄露)。为解决这一问题,解释器会定期执行一个循环检测器,搜索不可访问对象的循环并删除它们。

举例:v1和v2互相引用,把v1和v2del

v1 = [1, 5, 6]
v2 = [6, 9, 2]
v1.append(v2)
v2.append(v1)

del v1
del v2

Python是如何进行内存管理的?(图文讲解)

Python是如何进行内存管理的?(图文讲解)
v1和v2对象被干掉了,但是堆内存中有相互引用,引用计数位为1;可是没有变量去接收,这些内存地址程序员想用都不能用到,并且还占用内存。解决办法就是用标记清除。

注意:

1、栈内存、堆内存

栈内存:存放变量和内存地址
堆内存:存放值

2、内存溢出

由于内存是有限的,当计算机内存中存在大量的相互(循环)引用计数时,会占用大部分的内存;当新的变量进来时,但是内存不够用了,所以不会去开辟新的内存

3、GC的效率:

垃圾回收时,python不能进行其他的任务,频繁的垃圾回收将大大降低python的工作效率;
原因是GIL的存在,当GC运行的时候,会抢python解释器锁,其他线程处于阻塞状态,会降低python的工作效率;
所以GC的回收不要那么频繁;几个小时GC会运行一次,一次运行不到1秒;太不影响其他线程的工作了

4、GC的启动:

当python运行时,会记录其中分配对象和取消分配对象的次数。当俩者的差值高于某个阈值(默认为700)时,垃圾回收才会启动。

5、GC触发:

1、主动调用gc.collect()
2、GC达到阈值时自动触发
3、程序退出时(一次性全部退出)

1、标记清除

当应用程序可用的内存空间被耗尽时,就会停止整个程序,然后进行两项工作,标记和清除。

标记清除算法是一种基于追踪回收 技术实现的垃圾回收算法。它分为两个阶段:第一阶段是标记阶段,GC会把所有的『活动对象』(有引用的对象)打上标记,第二阶段是把那些没有标记的对象『非活动对象』进行回收。

2、分代回收(帮我们回收循环嵌套的引用

因为, 标记和清除的过程效率不高。清除非活动的对象前它必须顺序扫描整个堆内存,哪怕只剩下小部分活动对象也要扫描所有对象。还有一个问题就是:什么时候扫描去检测循环引用?

为了解决上述的问题,python又引入了分代回收。分代回收解决了标记清楚时什么时候扫描的问题,并且将扫描的对象分成了3级,以及降低扫描的工作量,提高效率。
存活时间越久的对象,越不可能在后面的程序中变成垃圾。

所有的新建对象都是0代对象
当某一代对象经历过垃圾回收,依然存活,那么他就被归入下一代对象了。
垃圾回收启动时,一定会扫描所有的0代对象
如果0代经过一定次数垃圾回收,那么就启动对1代的扫描清理;当1代也经历了一定次数的垃圾回收后,那么会启动对0,1,2,即对所有对象进行扫描

0代: 0代中对象个数达到700个(阈值),扫描一次。
1代: 0代扫描10次,则1代扫描1次。
2代: 1代扫描10次,则2代扫描1次。

三、Python的内存池

Python提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统。

对于Python对象,以下几种情况,都有其独立的私有内存池。字符串的驻留机制

1、字符串长度为0或者1
2、符合标识符的字符串(只包含字符数字下划线)
3、字符串只在编译时进行驻留,而非运行时
4、[-5,256]之间的整数数字

举例1:[-5,256]之间的整数数字

值相同内存地址也相同

>>> a=66
>>> b=66
>>> id(a)
2526627451280
>>> id(b)
2526627451280

值相同内存地址不同

>>> c=399
>>> d=399
>>> id(c)
2526635259696
>>> id(d)
2526635259536

原理图如下:

Python是如何进行内存管理的?(图文讲解)

举例2:符合标识符的字符串(只包含字符数字下划线)

>>> a="qwe%"
>>> b="qwe%"
>>> a is b
False
>>> c="123kobe"
>>> d="123kobe"
>>> c is d
True

举例3:字符串长度为0或者1

>>> e=""
>>> f=""
>>> e is f
True
>>> e="!"
>>> f="!"
>>> e is f
True

举例4:字符串只在编译时进行驻留,而非运行时

>>> a="kk"
>>> b="k"+"k"
>>> a is b
True
>>> a="kobe"
>>> b="".join('kobe')
>>> a is b
False

四、怎么优化内存管理

1.手动垃圾回收

先调用del a ; 再调用gc.collect()即可手动启动GC(嵌套的引用删除不了,因为引用计数为1)

2.调高垃圾回收阈值

gc.set_threshold 设置垃圾回收阈值(收集频率)。 将 threshold0 设为零会禁用回收。

gc.set_threshold(800,20,20)

3.避免循环引用


Python是如何进行内存管理的?(图文讲解)

Python是如何进行内存管理的?(图文讲解)文章来源地址https://www.toymoban.com/news/detail-497472.html

到了这里,关于Python是如何进行内存管理的?(图文讲解)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • python简单安装教程+图文讲解

    大家好,今天我给大家带来了新手级的python安装教程。 下面就 来看看吧    首先我们需要python安装包,获取途径: 1.csdn下载:   python安装及组件安装​​​​​ 2.123云盘 :    点击下载         提取码:Nsi5 首先,打开下载的安装包。 点击“下一步”(是2.5 安装的是

    2024年02月11日
    浏览(36)
  • idea如何设置注释模板,图文超详细讲解

    目录 先打开idea设置 一,idea类注释 1,找到以下设置 2,设置模板 3,apply保存完成 二,idea方法注释 1,创建自定义的组 2,创建模板 3,设置模板 4,选择生成模板的文件 5,绑定选择参数 6,完成ok 类注释模板和接口注释模板 方法注释模板 生成模板 /** +模板名+快捷键, 选择

    2024年02月14日
    浏览(48)
  • 如何卸载干净 IDEA(图文讲解)windows和Mac教程

    大家好,我是sun~ 很多小伙伴会问 Windows / Mac 系统上要怎么彻底卸载 IDEA 呢? 本文通过图片+文字,详细讲解具体步骤: Windows 系统要想彻底卸载 IDEA, 步骤如下: 点击屏幕左下角 Windows 图标 - 设置: 在应用中找到 IDEA, 单击它会出现卸载按钮,点击开始卸载: 勾选第一栏 De

    2024年02月06日
    浏览(59)
  • Visual Studio 2022 从下载安装到如何使用的全面讲解 (图文详解)

    🎬 鸽芷咕 :个人主页  🔥 个人专栏 :《C语言初阶篇》 《C语言进阶篇》 ⛺️生活的理想,就是为了理想的生活!    🌈 hello! 各位宝子们大家好啊,相信很多C语言的初学者,都在为学C语言用那个软件而发愁!    ⛳️ 那么今天就给大家推荐这款软件, Visual Studio 202

    2024年02月16日
    浏览(57)
  • 计算机网络基础知识(五)——什么是TCPUDP协议?图文并茂的方式对两大传输层协议进行从头到尾的讲解

    TCP和UDP协议是TCP/IP协议的核心。 TCP 传输协议:TCP 协议是一TCP (Transmission Control Protocol)和UDP(User Datagram Protocol)协议属于传输层协议。其中TCP提供IP环境下的数据可靠传输,它提供的服务包括数据流传送、可靠性、有效流控、全双工操作和多路复用。通过面向连接、端到端和可靠

    2024年02月05日
    浏览(57)
  • 【超详细图文讲解】如何利用VMware创建CentOS虚拟机(包括如何更改网络设置 + 远程访问虚拟机方法)

    本文主要掌握内容: 熟悉虚拟机软件的安装与配置. 练习建立一台虚拟机, 并配置其网络模式. 练习在虚拟机中安装 CentOS 7 系统, 了解配置过程. 学习在 Centos 7 中配置网络. 学习远程访问虚拟的方法. 学习配置 CentOS 7 的图形化和命令行交互方式, 学会关机, 重启等命令. 关注收藏

    2024年04月13日
    浏览(70)
  • Tenda腾达无线路由器如何升级? 腾达无线路由器升级方法步骤图文讲解

    本文档适用于需要 查看或升级路由器软件 的用户 适用类型:Tenda腾达无线路由器——问题分类:故障排除  1  请使用有线连接路由器升级,升级过程切勿切断电源,否则会导致路由器损坏而无法使用!  2  请查看路由器的当前软件版本信息及官网软件说明,确定路由器是否

    2024年02月06日
    浏览(43)
  • 无线路由器如何进行无线桥接的详细图文教程(推荐)

    工具/原料 网络 两台无线路由器(其中至少一台有桥接功能) 步骤一 配置PC环境 1、为保证后续无线桥接配置的正确和完整性,建议用网线连接路由器,并将本机的IP(IPv4)设置为固定,且确保该固定IP是与主路由器IP同网段。 2、单击“开始”按钮,输入“cmd”,按回车,再输

    2024年02月06日
    浏览(56)
  • GitHub教程:最新如何从GitHub上下载文件(下载单个文件或者下载整个项目文件)之详细步骤讲解(图文教程)

    在这篇博客中,我们将深入探讨如何从GitHub下载文件或整个项目。无论你是编程新手,还是资深开发者,本文都将提供简单易懂的指导,帮助你轻松掌握下载技巧。涵盖从单个文件下载到整个项目的下载,我们的目标是确保每位读者都能通过本文轻松实现从GitHub的下载需求。

    2024年04月10日
    浏览(93)
  • 【图文教程】腾达w311r如何进行ADSL(PPPOE)连接?

    如果家里有一个电信的有线网(台式机),放假了我想把我的笔记本带回家。家里的电脑又被兄弟姐妹给占了。我很想玩我的笔记本,可是没有网该怎么办呢?这个时候你就需要一台无线路由器连电信的猫(Modem)了。那么腾达w311r如何进行ADSL(PPPOE)连接?下面小编就为大家详细

    2024年02月07日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包