首页 > 其他分享 >垃圾回收机制

垃圾回收机制

时间:2024-05-14 08:59:43浏览次数:21  
标签:栈区 字符 编码 二进制 回收 --- 垃圾 机制 内存

垃圾回收机制

【一】什么是垃圾回收机制

  • 垃圾回收机制(GC机制)是python自带的机制

  • 专门用来回收变量值所占的内存空间

【二】在python中的垃圾

# 每次书写Python代码都会创建很多变量名和变量值
# 但是有很多变量名和变量值 用过一次就不用了
# ---> 被称之为垃圾 ---> 不会主动清理掉垃圾
# name = 'dream'
# print(name)
# del name
# print(name)
# 在python解释器内部自带了一个垃圾回收机制

【三】堆和栈的概念

堆区:变量名和值内存地址关联的区域

栈区:变量值存放的区域

【四】三个名词

引用计数为主,标记清除为辅助,分代回收

【1】引用技术

变量值被变量名指向的次数

看10被指向的次数
# x = 10  # 1次
# y = x  # 2次
# x = 11 #1次
# y = 12 #0次

【2】标记清除

当一个变量值被引用的时候,python自带的垃圾回收机制会定期扫描

若这个变量值有引用,则不管

若这个变量值没有引用,则标记

【3】分代回收

  • 新生代 ---> 第一次扫描发现没人占用 扔到新生代

  • 青春代 ---> 达到新生代扫描阈值后,若还没人指向他,则挪到青春代

  • 老年代 ---> 达到青春代扫描阈值后,若还没人指向他,则挪到青春代

  • 清除--->达到老年代扫描阈值后,若还没人指向直接清除 del

【4】补充

# 【1】堆区
# 变量值存放于堆区,内存管理回收的则是堆区的内容
# # 在Python中,变量和它们所引用的对象(如数值、字符串、列表、字典等)的存储位置与内存管理机制密切相关。
# # 这里提到的“变量值存放于堆区”主要涉及两个概念:变量本身和它所引用的对象。
# # 1. 变量
#    变量是程序中用于标识数据的一个符号或名字,它并不直接存储数据,而是指向(或引用)实际存储数据的内存地址。
#    在Python解释器内部,变量名通常保存在栈(Stack)中。栈是一种后进先出(LIFO)的数据结构,用于高效地管理函数调用时的局部变量、返回地址等信息。
#    当创建一个变量时,Python会在当前作用域(如全局作用域或函数局部作用域)的栈空间内为该变量分配一个名称,并将其关联到相应的对象。
# # 2. 对象及值
#    Python中的对象(即变量所引用的实际数据)通常存储在堆(Heap)中。
#    堆是一种动态分配内存的区域,相比于栈,其大小更为灵活且无固定上限。
#    堆用于存储需要大量、不固定大小内存空间的数据结构,如大数组、复杂的数据类型(如类实例)、以及那些生命周期可能跨越多个函数调用或作用域的对象。
# # 将对象值存放在堆区有以下几个原因:
# # - 灵活性
# 		堆内存的大小可以动态调整,能够适应不同大小和复杂度的对象。
#     这使得Python可以在运行时根据需要创建任意大小的对象,无需预先确定其具体尺寸,非常适合处理变长数据结构(如列表、字典)。
# # - 共享性
# 		多个变量可以同时引用同一块堆内存中的对象,实现对象的共享。
#     这种机制允许通过赋值、参数传递、返回值等方式高效地复制“引用”,而不是复制整个对象内容,节省了内存资源并提高了效率。
# # - 垃圾回收
# 		由于堆内存中的对象可能存在多个引用,Python使用垃圾回收(Garbage Collection, GC)机制自动追踪和管理对象的生命周期。
#     当一个对象不再有任何引用时,GC会识别并释放其占用的堆内存,防止内存泄漏。
#     堆区便于实施这样的垃圾回收策略,确保程序长期运行时内存的有效利用。
# # 综上所述
# 		Python将变量值(即对象)存放于堆区,主要是为了提供灵活的内存分配、支持对象共享以及实现自动化的垃圾回收,这些特性对于编写高效、健壮的Python程序至关重要。
#     而变量本身作为对象的引用,则通常存储在栈区,便于快速访问和管理其生命周期。


# 【2】栈区
# 变量名与值内存地址的关联关系通常被存放于程序的栈区

# # 1. 栈区的特性与作用
#    栈(Stack)是计算机内存中的一种数据结构,其主要特点是后进先出(LIFO)。在编程语言执行过程中,栈区用于存储局部变量、函数参数以及函数调用时的返回地址等临时性信息。
#    栈区的操作快速且高效,因为它遵循简单的压栈(push)和弹栈(pop)规则,适合处理那些生命周期短、使用频繁且需要保持特定顺序的数据。
# # 2. 变量生命周期管理
#    变量名与值内存地址的关联关系本质上是一种符号表信息,它记录了源代码中定义的变量名与其所对应的内存地址之间的映射。
#    这种信息具有明显的生命周期特征:当进入一个作用域(如函数或代码块)时,新声明的变量及其关联关系应被创建;
#    当离开该作用域时,这些变量及关联关系应被自动清理以释放资源。栈区恰好符合这种对变量生命周期进行严格管理的需求。
#    每当函数调用发生时,会在栈顶为该函数分配一块空间,用于存放其内部声明的变量及其关联关系;函数调用结束时,这部分栈空间会被自动回收
# # 3. 性能优化
#    栈区访问速度极快,因为它的内存地址通常连续且靠近CPU寄存器。将变量名与值内存地址的关联关系放在栈上,可以确保编译器和运行时系统能以较低的时间成本查找并操作这些信息。特别是在递归调用、循环等频繁涉及变量访问的场景下,栈区的高效访问对于提升程序整体性能至关重要
# # 4. 内存安全性
#    栈区的内存由编译器自动分配和释放,不易出现内存泄漏问题。将变量名与值内存地址的关联关系存储在栈上,有助于防止因程序员手动管理内存不当而导致的错误。此外,栈区的大小通常有限制,这有助于防止因局部变量过度使用内存而导致的堆栈溢出问题,从而提高程序稳定性
# # 5. 线程安全性
#    每个线程都有自己的栈空间,这意味着不同线程中的同名局部变量各自拥有 ** 的内存地址和关联关系,互不影响。这一特性保证了并发环境下的数据安全,避免了线程间的数据混淆。
# # 综上所述
#     将变量名与值内存地址的关联关系存放于栈区,既利用了栈区的特性实现了高效的内存管理、快速访问和严格的生命周期控制,又确保了内存安全性与线程安全性,有利于编写稳定、高效且易于维护的程序代码。
#   当然,需要注意的是,上述讨论主要针对局部变量。
#   对于静态变量、全局变量或动态分配的对象,它们的内存地址关联关系可能存在于数据段(Data Segment)或堆区(Heap),而非栈区。

【5】小整数池

# [-5,256] ---> 提前开辟好一块内存空间存储这些数据
# 为了防止频繁的使用数字减少开销
# 不需要每次定义的时候都开辟空间,只需要从开辟好的空间中获取即可

a = 10
b = 10
print(a is b)

True

字符编码

  • 为什么学字符编码
  • 不同国家有不同文字,怎样让python代码识别不同国家的文字
  • 指定好指定的模板让python使用

【一】数据存放位置

我们学的所有数据都存放在内存当中

如何将数据保存到硬盘中

【二】字符编码介绍

  • 计算机能识别的文字(二进制数据)与我们能识别的文字之间的对应关系做成的编码表

  • 人类与计算机交互的时候,计算机展示出来的内容都是人类可以看得懂的

  • 我们都知道计算机只能识别二进制数据

  • 二进制就是 0 / 1

  • 要学习如何将我们的文字转换成计算机可以识别的文字

【三】字符编码的发展史

# 字符编码是如何从 0 / 1 -----> 文字 / 字符

【1】一家独大

美国人发明计算机 ---> 美国人用英语(英语字符)
0 / 1 编码麻烦  ---> 用字符代表一串代码 
---> ASCII 码表 ---> 大小写英文字符 / 数字 / 标点符号
大写英文字母 A-Z : 65 -90
小写英文字母 a-z : 97-122
数字 0 - 9 : 48 - 57

【2】诸侯割据

随着计算机的普及 其他国家的人也能拿到计算机
基于ASCII码表继续扩展,扩展成各个国家的编码表
于是出现了很多编码表
日本 Shift_JIS
中国 GBK

# 问题诞生
# 有一天美国的程序员(ASCII码)拿着他写的代码来找中国人开发
# 韩国人(Euc-kr) --> 中国人开发
# 很多个国家的编码表我都需要保存一遍

【3】一统天下

大家统一意见,合理开发一个编码表,作为所有国家的标志
# Unicode : 存在所有语言中的所有字符与数字的一一对应关系,即兼容万国字符
# 自己国家的字符存储在硬盘中的
# 如果要使用 ---> 读出来 ---> 展示
# 美国人--ascii ---> unicode ----> gbk ---> 中文
# 日本人--shift-jis ---> unicode ----> gbk ---> 中文

【四】如何进行编解码(二进制)

# 1.解码---> 将二进制数据转换为字符
data = b'\xe7\x8e\x8b'
print(data.decode('utf-8'))
# print(data.decode('gbk'))
# print(data.decode('shift-jis'))
王

# 2.编码
name = '王'
# 指定编码格式--->哪种语言的二进制数据

print(name.encode('utf-8'))

b'\xe7\x8e\x8b'

name1 = b'yi'
print(type(name1))

<class 'bytes'>

【五】UTF-8的诞生

# 【1】一开始的保存方案
# 如果保存到硬盘的是GBK格式二进制,当初用户输入的字符只能是中文或英文
# 同理如果保存到硬盘的是Shift_JIS格式二进制,当初用户输入的字符只能是日文或英文……
# 如果我们输入的字符中包含多国字符,那么该如何处理?
# 多国字符—√—>内存(unicode格式的二进制)——X—>硬盘(GBK格式的二进制)
# 多国字符—√—>内存(unicode格式的二进制)——X—>硬盘(Shift_JIS格式的二进制)
# 多国字符—√—>内存(unicode格式的二进制)——√—>硬盘(???格式的二进制)

# 【2】解决办法(utf-8)
# 多国字符—√—>内存(unicode格式的二进制)——√—>硬盘(utf-8格式的二进制)

# 【3】utf8不够用
# 颜文字 ---> utf8mb4

# 【4】最后
# 随着时代的发展 可能 unicode 就被淘汰了 只剩下 utf8

【六】补充

#python2.x 文件头
# --*-- utf-8
当前文件编码强制使用utf8
# 不要随意修改自己文件的编码格式
# 默认的编码格式全都是UTF-8
# 如果修改了源文件的编码格式造成的后果就是数据找不回来了

![屏幕截图 2024-04-09 090030](D:\29期笔记\09\垃圾回收机制.assets\屏幕截图 2024-04-09 090030.png)

标签:栈区,字符,编码,二进制,回收,---,垃圾,机制,内存
From: https://www.cnblogs.com/yi416/p/18190495

相关文章

  • 字节面试:说说Java中的锁机制?
    Java中的锁(Locking)机制主要是为了解决多线程环境下,对共享资源并发访问时的同步和互斥控制,以确保共享资源的安全访问。锁的作用主要体现在以下几个方面:互斥访问:确保在任何时刻,只有一个线程能够访问特定的资源或执行特定的代码段。这防止了多个线程同时修改同一资源导致的数据......
  • Android Overlay 机制
    什么是overlayAndroidOverlay是一种资源替换机制,它能在不重新打包apk的情况下,实现资源文件的替换(res目录非assert目录),Overlay又分为静态Overlay(StaticResourceOverlay)与运行时Overlay(RuntimeResourceOverlay)。是用来更好的实现packages下面、framework一些关于资源文件......
  • 【TransmittableThreadLocal】TransmittableThreadLocal的实现机制和原理
    1 前言前面我看过了 ThreadLocal的实现机制和原理 以及 InheritableThreadLocal的实现机制和原理 两种类型的ThreadLocal,前者是普通的,后者是在前者的基础上套了一层父子线程关系,当使用后者的时候,会在线程创建的时候,浅拷贝一份父线程的变量值。那么今天空了,我来看看另外一......
  • 事件循环(event loop)原理,并类比理解qt的信号(Signal)和槽(Slot)机制)
    背景:实际项目中要使用pyqt/pyside技术,涉及到qt和asyncio的事件循环,并需要使用到qt的信号(Signal)和槽(Slot)机制,从底层了解事件循环的原理使得后续工作更好入手。事件循环是什么?事件循环(EventLoop)是一种用于处理和调度异步任务的机制。它通常用于编写异步编程,特别是在处理IO密......
  • 2391. 收集垃圾的最少总时间
    传送锚点:https://leetcode.cn/problems/minimum-amount-of-time-to-collect-garbage/description/给你一个下标从0开始的字符串数组garbage,其中garbage[i]表示第i个房子的垃圾集合。garbage[i]只包含字符'M','P'和'G',但可能包含多个相同字符,每个字符分别表示一单位......
  • jvm内存模型、垃圾回收机制
    JVM内存模型JVM内存模型包括:线程计数器、本地方法栈、栈、堆、方法区(元空间),类装载子系统,字节码执行引擎。线程计数器线程启动时,程序技术会分配一小块空间分配给当前线程,每个线程都会独享一块程序计数器空间,用于存储下条指令的单元地址程序计数器是一块较小的内存空间,用于......
  • 理解 Swift 中闭包与 Objective-C 中 Block 的外部变量捕获机制
    在Swift中的闭包和Objective-C中的Block都支持捕获外部变量,使得在闭包或Block内部可以访问外部作用域的变量。本文将深入探讨它们在捕获外部变量方面的机制和区别。1.Swift中闭包的外部变量捕获机制在Swift中,闭包捕获外部变量时会根据情况选择采用值捕获(Captureby......
  • Kafka存储机制
    Kafka之所以有那么高的吞吐量,很大程度取决于它的存储机制,一个主题可以有多个partition,每个partition有一个leader和多个副本,读写主要通过leader,副本的主要功能还是为了保证数据的安全性和保证可靠性,当某个partition的leader出现异常后,剩余副本可以选举出新的leader;每个partition......
  • iceoryx源码阅读(八)——IPC通信机制
    目录1 整体结构2 序列化与反序列化3 类Unix系统的实现3.1 发送函数send3.2 接收函数receive4 Windows系统的实现4.1 发送函数send4.2 接收函数receive5 Roudi的监听逻辑1 整体结构通过前面的介绍,订阅者、发布者与Roudi守护进程之间也需要通信,如上文介绍的,请求Roudi守护进村创建......
  • 细说夜莺监控系统告警自愈机制
    虽说监控系统最侧重的功能是指标采集、存储、分析、告警,为了能够快速恢复故障,告警自愈机制也是需要重点投入建设的,所有可以固化为脚本的应急预案都可以使用告警自愈机制来快速驱动。夜莺开源项目从v7版本开始内置了告警自愈模块,本文将详细介绍告警自愈的原理和实现。夜莺项目......