首页 > 编程语言 >python中级之垃圾回收机制

python中级之垃圾回收机制

时间:2023-12-04 16:26:38浏览次数:47  
标签:中级 变量 python 堆区 回收 列表 计数 垃圾 引用

引入

image

当解释器在执行到变量赋值的时候,例如:name = 'xiaoying',那么会向内存空间申请一块空间来存放变量的值,而内存的空间是有限的,并不能无限制的存放,那么这就涉及到了一个回收的问题,当一个变量值没用了之后,简称(垃圾),那么垃圾就该放进垃圾桶中进行回收,将其所占用的内存空间释放回收掉。那么什么样的变量是没有用的呢?

从逻辑方面分析,定义的变量是为了后续将其引用,要通过内存的门牌号找到该变量对其进行直接引用或者间接引用,所以当一个变量值没有被任何的'人'引用时,就称之他为垃圾,而垃圾自然是不被需要的,所以就需要将他回收掉
'''
一、直接引用
    x = 10
    print(x)

二、间接引用
    l = ['a','b',x]
    print(l[2])
'''
而CPython就为我们提供了这样 的回收机制来帮助我们将'垃圾回收'

什么是垃圾回收机制?

垃圾回收机制(简称GC)是Python解释器自带一种机制,专门用来回收不可用的变量值所占用的内存空间

为什么要用垃圾回收机制?

程序运行过程中会申请大量的内存空间,而对于一些无用的内存空间如果不及时清理的话会导致内存使用殆尽(内存溢出),导致程序崩溃,因此管理内存是一件重要且繁杂的事情,而python解释器自带的垃圾回收机制把程序员从繁杂的内存管理中解放出来。

垃圾回收机制储备知识

堆区和栈区

  • 在定义变量时,变量名与变量值都是需要存储的
  • 分别对应内存中的两块区域:
    • 堆区
      • 变量名与值内存地址的关联关系存放于栈区
    • 栈区
      • 变量值存放于堆区,内存管理回收的则是堆区的内容,
  • 示例
    • 定义了两个变量x = 10、y = 20,详解如下图

image

  • 当我们执行x=y时,内存中的栈区与堆区变化如下

image

直接引用和简介引用

  • 直接引用指的是从栈区出发直接引用到的内存地址。
  • 间接引用指的是从栈区出发引用到堆区后,再通过进一步引用才能到达的内存地址。
l2 = [20, 30] # 列表本身被变量名l2直接引用,包含的元素被列表间接引用 
x = 10  	  # 值10被变量名x直接引用
l1 = [x, l2]  # 列表本身被变量名l1直接引用,包含的元素被列表间接引用
  • 图解

image

垃圾回收机制原理分析

Python的GC模块主要运用了“引用计数”(reference counting)来跟踪和回收垃圾。在引用计数的基础上,还可以通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用的问题,并且通过“分代回收”(generation collection)以空间换取时间的方式来进一步提高垃圾回收的效率。

引用计数

image

'''
引用计数:顾名思义就是变量值被变量名关联的次数,例如:
        name = 'xiaoying'
        这里xiaoying被变量名name所关联,引用计数就 +1

引用计数的增加:之前name = 'xiaoying'  # 此刻引用计数为1
             那么将name在赋予给一个变量名,例如:
             x = name  # 将name的内存地址也给到了x,此时x与name都关联到了'xiaoying'的内存地址,此刻引用计数为2

引用计数的减少:可以通过解绑的方式,这里通过del来完成,例如
             del x  # del的意思是解除变量名x与变量值之间的关联关系,此时引用计数就 -1
             或者
             name = 'cc'  # name先与值'xiaoying'解除关联,再与'cc'建立了关联,变量值'xiaoying'引用计数 -1,此刻'xiaoying'的内存地址引用计数为0,那么久将触发GC机制回收

'''

image

引用计数扩展阅读--循环引用

变量值的关联+1或者减少,都会触发引用计数的机制,这就存在了效率问题。如果说单单只存在执行效率的话,那么还是幸运的,但引用计数还存在着一个致命的问题,即是循环引用。
'''
# 定义两个列表
l1 = [111, ]  # 列表[111,],引用计数+1
l2 = [222, ]  # 列表[222,],引用计数+1

l1.append(l2)  # l1=[值111的内存地址,l2列表的内存地址]  
l2.append(l1)  # l2=[值222的内存地址,l1列表的内存地址]
# 两个列表之间存在相互引用,在当将两个之间的关联解除是,但是值的引用并不会因为解除而变为0,那么就不会触发GC机制将占用的内存空间回收,例如:
del l1  # 列表1的引用计数减1,列表1的引用计数变为1
del l2  # 列表2的引用计数减1,列表2的引用计数变为1
'''
此刻,两个列表之间的引用计数都为1,是两个列表互相引用,但两个列表都没有被任何对象关联,所以无法再引用到他们,所以他们两个所占用的内存空间应该被回收,但由于互相引用在,之前的引用计数则不会有作用,无疑这样的问题是致命的,所以Python引入了"标记清除"和"分代回收"来解决效率与循环引用的问题

标记-清除

容器的对象,例如:列表,字典,集合,类等等可以包含对其他对象的引用,都可能产生循环引用的问题,标记清除就是解决循环引用问题的机制
关于变量的存储,在内存中有两块区域:堆区和栈区,其中变量名在内存栈区,变量名存的是内存地址,变量值在内存堆区,GC机制回收的是堆区的内容

image

当我们执行x = y时,内存空间中则会发生这样的变化

image

将原来x 与 10的绑定关系解除,x 与 20绑定在一块
标记清除算法的做法是当应用程序可用的内存空间被耗尽的时候,就会停止整个程序,然后进行两项工作,第一项是标记,第二项则是清除

'''
# 1、标记:
    标记的过程就是遍历所有的GC Roots对象(栈区中所有的内容或者线程都可以作为GC Roots对象),然后将所有GC Roots对象可以直接访问到的或者间接访问到的标记为存活,其余则应该被清除
    通俗来说,就是标记的整个过程相当于从栈区出发的一条连接线,连到堆区后,再由堆区连到对应的内存地址,凡是可以被这条从栈区出发的线找到的,则都标记为存活
'''
例如之前的两个列表可以做图得到对应的关系:

image

当我们同时del l1   del l2之后

image

这样的话在标记清除的机制下,发现栈区中不在有一条'线'可以连接到堆区的值,只剩下堆区的l1与l2相互引用,于是这两个列表都不会被标记为存活,两者都会被清理掉,这样就解决了循环引用带来的问题

分代回收

背景

基于引用计数的回收机制,每次回收内存,都需要把所有对象的引用计数都遍历一遍,这是非常消耗时间的,于是引入了分代回收来提高回收效率,分代回收采用的是用“空间换时间”的策略。

分代

分代回收的核心思想是:在历经多次扫描的情况下,都没有被回收的变量,gc机制就会认为,该变量是常用变量,gc对其扫描的频率会降低,具体实现原理如下:
分代指的是根据存活时间来为变量划分不同等级(也就是不同的代)

新定义的变量,放到新生代这个等级中,假设每隔1分钟扫描新生代一次,如果发现变量依然被引用,那么该对象的权重(权重本质就是个整数)加一,当变量的权重大于某个设定得值(假设为3),会将它移动到更高一级的青春代,青春代的gc扫描的频率低于新生代(扫描时间间隔更长),假设5分钟扫描青春代一次,这样每次gc需要扫描的变量的总个数就变少了,节省了扫描的总时间,接下来,青春代中的对象,也会以同样的方式被移动到老年代中。也就是等级(代)越高,被垃圾回收机制扫描的频率越低

回收:

回收依然是使用引用计数作为回收的依据

image

虽然分代回收可以起到提升效率的效果,但也存在一定的缺点:

#例如一个变量刚刚从新生代移入青春代,该变量的绑定关系就解除了,该变量应该被回收,但青春代的扫描频率低于新生代,所以该变量的回收就会被延迟。

标签:中级,变量,python,堆区,回收,列表,计数,垃圾,引用
From: https://www.cnblogs.com/xiao01/p/17875204.html

相关文章

  • Python字符编码
    编码,文字和二进制之间的一个对照表。【1】阶段一:一家独大(ASCII)(1)ASCII表的诞生现代计算机起源于美国,所以最先考虑仅仅是让计算机识别英文字符,于是诞生了ASCII表(2)ASCII表的特点只有英文字符与数字的一一对应关系一个英文字符对应1Bytes,1Bytes=8bit,8bit最多包含256个数字,......
  • 通过Python和大数据技术实现网站内容的个性化推荐
    随着互联网的快速发展,越来越多的人使用网络来获取信息和娱乐。在这个过程中,推荐系统成为了一个非常重要的工具,通过分析用户的行为和偏好,提供个性化的推荐内容,提升用户的体验和满意度。本文将介绍如何使用Python和大数据技术实现网站内容的个性化推荐。一、推荐系统的分类推荐系统根......
  • 如何使用Python提升网站的SEO效果
     Python是一种功能强大的编程语言,可以应用于各种领域,包括优化网站的搜索引擎优化(SEO)效果。本文将探讨如何使用Python来改善网站的SEO效果,并提供一些实用的技巧和工具。 1.网站地图生成器:网站地图是搜索引擎索引网页的重要工具之一。使用Python可以编写脚本来自动生成网站地图,以......
  • 软件测试/人工智能|Python 数据类型解析:探索编程世界的多样性
    数据类型是编程中不可或缺的基本概念。在Python中,有多种数据类型,每种都有其独特的特点和用途。本文将带你深入了解常见的Python数据类型及其实际应用。引言在编程中,数据类型是对数据进行分类和组织的方式。Python中有多种数据类型,每种类型都有其自身的特性和功能。了解这......
  • 软件测试/人工智能|Python 数据类型转换解析:理解数据之间的灵活转换
    引言数据类型转换是指将一种数据类型的值转换为另一种数据类型的过程。在编程中,我们经常需要处理不同类型的数据,正确地进行类型转换是编写健壮程序的关键。常见的数据类型转换整数和浮点数转换为字符串#示例代码num_int=10num_float=3.14str_int=str(num_int)str......
  • GC垃圾回收机制
    【一】垃圾回收机制是什么专门用来回收不可用的变量值所占用的内存空间(在内存中,没有变量名指向的数据都是垃圾数据)【二】为什么要有垃圾回收机制程序运行过程中会申请大量的内存空间,而对于一些无用的内存空间如果不及时清理的话会导致内存使用殆尽(内存溢出),导致程序崩溃因此......
  • 软件测试/人工智能|Python 变量解析:从基础概念到内存地址探究
    变量什么是变量?变量是在程序中用于存储数据的名称。它们可以存储各种类型的数据,比如数字、文本、列表、字典等等。变量类型在介绍变量时,可以提及Python中常见的变量类型,例如整数、浮点数、字符串、布尔值、列表、元组、字典等。如下所示:a=1b='muller'c='123'd=......
  • Python函数介绍
    1.函数1.1函数概述函数定义和优势不同形状正方形打印#2个foriinrange(0,2):forjinrange(0,2):print("*",end="")print()#3个foriinrange(0,3):forjinrange(0,3):print("*",end="")pr......
  • python之字符编码
    【字符编码的发展史】一家独大:ASCII(识别英文字符)-------------诸侯割据(ASCII/GBK/Shift_JIS)---------------一统天下(存在所有语言中的所有字符与数字的一一对应关系,即兼容万国字符,unicode) 字母对应ASCII表A-Z:65-90a-z:97-1220-9:48-57小写字母对应的数字一定大于大写字母 ......
  • Java开发者的Python快速实战指南:探索向量数据库之图像相似搜索-文字版
    首先,我要向大家道个歉。原本我计划今天向大家展示如何将图片和视频等形式转换为向量并存储在向量数据库中,但是当我查看文档时才发现,腾讯的向量数据库尚未完全开发完成。因此,今天我将用文本形式来演示相似图片搜索。如果您对腾讯的产品动态不太了解,可以查看官方网址:https://cloud.t......