比较Python和Rust的内存管理机制
大家好,内存管理是编程语言的基础,它确保着资源被有效利用,不同的编程语言采用不同的策略来管理内存。有些语言需要程序员手动管理内存,有些语言则自动化了内存管理过程。Python和Rust都采用了垃圾收集(Garbage Collection)机制来管理内存,但它们各自的实现方式有很大的不同。
1.Python:引用计数与分代式垃圾收集
Python使用称为“引用计数”的技术进行垃圾收集,每个对象都有一个计数器,跟踪对其的引用数量。当此计数达到零时,对象就会从内存中删除。
换句话说,每个内存中的对象都有一个关联的数字(称为“引用计数”),跟踪它被多少变量或其他对象指向。
import sys# 创建对象x
x = [1, 2, 3]# 获取x的引用计数(应该是1)
print("Reference Count of x:", sys.getrefcount(x) - 1)# 创建x的引用
y = x# 引用计数增加 1
print("Reference Count of x after y = x:", sys.getrefcount(x) - 1)# 删除引用
del y# 引用计数减少 1
print("Reference Count of x after del y:", sys.getrefcount(x) - 1)
Reference Count of x: 1
Reference Count of x after y = x: 2
Reference Count of x after del y: 1
Python采用称为“分代垃圾收集”的生成式方法,来进一步提高垃圾收集的效率。对象分为三个不同的“代”:
-
Generation 0:新对象
对象最初分配在第0代,这是其生命周期的第一阶段。
# 导入 gc(垃圾回收)模块
import gc# 启用调试以打印垃圾收集信息
gc.set_debug(gc.DEBUG_STATS)# 创建一个新的列表对象;该对象最初处于第 0 代
new_object = [1, 2, 3]# 仅在第 0 代手动运行垃圾回收
gc.collect(0)
创建new_object时,它是一个新对象,会在第0代开始其生命
-
Generation 1:经历过一次垃圾回收周期的对象
在第0代垃圾回收周期中未被回收的对象会转移到第1代。
# 创建一个持久对象
persistent_object = {"key": "value"}# 在第 0 代运行垃圾回收
gc.collect(0)# 此时,"persistent_object "存活并进入第 1 代
在Python的分代式垃圾收集中,当一个对象首次建时,它会被放入第0代。每当对该代进行垃圾收集循环时,Python会寻找不再需要的对象(即引用计数为零的对象),以删除它们并释放内存。
如果像persistent\_object一样的对象在这个垃圾收集周期中存活下来,这意味着它仍在被引用或使用,它就会 "老化 "并进入下一代,在这种情况下是第1代。
这背后的原理是,新创建的对象更有可能是短命的,会很快被垃圾回收。另一方面,如果一个对象已经经历过一次垃圾回收周期,那么它就更有可能是长寿的,因此它会被转移到较老的一代,接受较少频率的检查。
由于persistent_object仍在使用中(在代码中的某个地方被引用),它的引用计数并不为零,因此它能在第0代垃圾回收过程中存活下来。
-
Generation 2:存活超过一个垃圾回收周期的对象
经过多次垃圾收集周期的对象最终会转到第2代。
# 创建另一个持久对象
very_persistent_object = (1, 2, 3)# 对第 0 代和第 1 代进行垃圾回收
gc.collect(0)
gc.collect(1)# 此时,"very_persistent_object "存活下来,并应进入第 2 代
在这里,very_persistent_object在第0代和第1代的垃圾回收中都能存活,因此它将转移到第2代。
实际上,开发者通常不需要手动控制或监控这些生成,Python 的垃圾回收器会自动处理,但了解它们的工作原理对调试和优化很有帮助。
2.Rust:基于所有权和借用的内存管理
Rust的内存管理方式与具有垃圾收集的语言(如Python)有着本质区别,它依赖于“所有权”和“借用”的概念来确保资源的安全管理。
2.1 所有权
在Rust中,每个值都有一个“所有者”,该值在其所有者存在时有效。当所有者超出范围时,该值及其资源会被自动释放,这样就不需要单独的垃圾回收过程了。
以下是个示例:
fn main() {let s1 = String::from("hello"); // s1是值"hello"的所有者let s2 = s1; // s1的所有权被传递给s2// println!("{}", s1); // 这将导致错误,因为s1不再拥有该值println!("{}", s2); // 这是可以的,s2现在是所有者
} // s2超出范围,“hello”被释放
在本例中,s1最初拥有字符串 "hello",然后所有权转移到s2。当s2在main()的结尾超出范围时,字符串"hello"会被自动释放。
2.2 借用
有时,需要访问一个值而不需要取得其所有权,因此 Rust 允许 "借用",可以借用一个可变或不可变的引用值。
不可变借用:
fn main() {let s1 = String::from("hello");let len = calculate_length(&s1); // &s1借用s1而不拥有它println!("'{}'的长度为{}.", s1, len);
}fn calculate_length(s: &String) -> usize {s.len()
}
可变借用:
fn main() {let mut s1 = String::from("hello");change_string(&mut s1); // &mut s1以可变引用形式借用s1println!("{}", s1);
}fn change_string(s: &mut String) {s.push_str(", world");
}
在这些示例中,&s1和&mut s1借用了值,但没有取得所有权,从而允许 s1在函数调用后继续使用。
Rust 方法的主要优势在于,它可以精确控制代码的哪些部分可以使用、修改或取消分配值,从而使程序更安全、更高效,而无需进行垃圾收集。
相关文章:
比较Python和Rust的内存管理机制
大家好,内存管理是编程语言的基础,它确保着资源被有效利用,不同的编程语言采用不同的策略来管理内存。有些语言需要程序员手动管理内存,有些语言则自动化了内存管理过程。Python和Rust都采用了垃圾收集(Garbage Collec…...
Linux系统——Shell脚本——一键安装LNMP
#!/bin/bash #安装nginx echo "安装nginx服务" wget http://nginx.org/download/nginx-1.11.4.tar.gz &>/dev/null if [ $? -eq 0 ] thenecho "nginx-1.11.4安装包下载完成"echo "--开始安装必要的依赖文件--"yum install -y gcc gcc-c…...
算法复习之二分【备战蓝桥杯】
二分模板一共有两个,分别适用于不同情况。 算法思路:假设目标值在闭区间[l, r]中, 每次将区间长度缩小一半,当l r时,我们就找到了目标值。 版本一 当我们将区间[l, r]划分成[l, mid]和[mid 1, r]时,其更…...
如何做代币分析:以 SHIB 币为例
作者:lesleyfootprint.network 编译:cicifootprint.network 数据源:SHIB Token Dashboard (仅包括以太坊数据) 在加密货币和数字资产领域,代币分析起着至关重要的作用。代币分析指的是深入研究与代币相关…...
Springboot+vue的考勤管理系统(有报告)。Javaee项目,springboot vue前后端分离项目。
演示视频: Springbootvue的考勤管理系统(有报告)。Javaee项目,springboot vue前后端分离项目。 项目介绍: 采用M(model)V(view)C(controller)三层…...
https://htmlunit.sourceforge.io/
https://htmlunit.sourceforge.io/ 爬虫 HtmlUnit – Welcome to HtmlUnit HtmlUnit 3.11.0 API https://mvnrepository.com/artifact/net.sourceforge.htmlunit/htmlunit/2.70.0 https://s01.oss.sonatype.org/service/local/repositories/releases/content/org/htmlunit…...
回文链表(leetcode)
我自己第一个写的代码: bool isPalindrome(struct ListNode* head){struct ListNode* tail NULL;struct ListNode* pos NULL;if( head->next NULL){return true;}while( 1 ){if( head->next NULL || (head->next->next NULL && head->…...
大语言模型(LLM)技术名词表(一)
LLMs on a Phone:指在手机设备上运行的大型语言模型。 Scalable Personal AI:指用户可以在个人设备上对AI模型进行微调的技术。 Responsible Release:发布AI模型时考虑社会、法律和伦理影响的做法。 Multimodality:AI模型能处理…...
C++ 快速排序快速选择
目录 1、75. 颜色分类 2、912. 排序数组 3、 215. 数组中的第K个最大元素 4、LCR 159. 库存管理 III 1、75. 颜色分类 思路:利用快速排序思路,使用三指针分块进行优化。 [0,left]——小于key[left1,right-1]——等于key[right,nums.size()]——大于k…...
雅马哈伺服器TS-S系列说明具体详情内容可参看PDF目录内容
雅马哈伺服器TS-S系列说明具体详情内容可参看PDF目录内容...
SpringBoot底层原理
SpringBoot底层原理 一 配置优先级 1.配置方式 Springboot中支持三种配置方式,分别为: application.propertiesapplication.ymlapplication.yaml 2.配置优先级 当存在多份配置文件时,配置文件会按照它们的优先级生效。 优先级从高到底…...
【golang】25、图片操作
用 “github.com/fogleman/gg” 可以画线, 框 用 “github.com/disintegration/imaging” 可以变换颜色 一、渲染 1.1 框和字 import "github.com/fogleman/gg"func DrawRectangles(inPath string, cRects []ColorTextRect, fnImgNameChange FnImgNameChange) (st…...
kswapd0挖矿病毒攻击记录
文章目录 一、起因与病毒分析1、起因2、阿里云告警2.1 恶意脚本代码执行12.2 恶意脚本代码执行22.3恶意脚本代码执行32.4 恶意脚本代码执行4 3、病毒简单分析3.1 病毒的初始化3.2 病毒本体执行 4、总结 二、ubuntu自救指南1、病毒清理2、如何防御 一、起因与病毒分析 1、起因 …...
如何使用 takeUntil RxJS 操作符来声明性地管理订阅
简介 Angular 处理取消订阅可观察对象的操作,比如从 HTTP 服务返回的可观察对象或者使用 async 管道时。然而,对于其他情况,管理所有订阅并确保取消长期存在的订阅可能会变得困难。而且,取消大部分订阅的策略也会带来自己的问题。…...
在Centos中用Docker部署oracle-12c
一、介绍 Oracle 12c是Oracle 11g的后续版本。12c代表云计算(Cloud Computing),这是Oracle在该版本中强调的一个关键概念。它具有多租户架构、数据库内存、安全增强、大数据管理和自动化管理等功能。它被广泛应用于企业级应用程序和大型数据…...
JS进阶——高级技巧
版权声明 本文章来源于B站上的某马课程,由本人整理,仅供学习交流使用。如涉及侵权问题,请立即与本人联系,本人将积极配合删除相关内容。感谢理解和支持,本人致力于维护原创作品的权益,共同营造一个尊重知识…...
TG-ADMIN 权限管理系统
项目简介 该项目是一款基于 SpringBoot + Vue2 + Jwt + ElementUi的 RBAC模型管理系统。 主要以自定义拦截器和jwt结合进行权限验证 通过自定义指令实现按钮级别权限,使用经典的RBAC模型 什么是RBAC? 1、RBAC模型概述 RBAC模型(Role-Based Access Control:基于角色的…...
十五届蓝桥杯第三期模拟赛题单(C++、java、Python)
备战2024年蓝桥杯 省赛第三期模拟赛题单 备战Python大学A组 第一题 【问题描述】 请问 2023 有多少个约数?即有多少个正整数,使得 2023 是这个正整数的整数倍。 【问题描述】 这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果…...
嵌入式驱动学习第一周——git的使用
前言 本文主要介绍git的使用,包括介绍git,gitee,以及使用gitee创建仓库并托管代码 嵌入式驱动学习专栏将详细记录博主学习驱动的详细过程,未来预计四个月将高强度更新本专栏,喜欢的可以关注本博主并订阅本专栏…...
界面控件DevExpress .NET MAUI v23.2新版亮点 - 拥有全新的彩色主题
DevExpress拥有.NET开发需要的所有平台控件,包含600多个UI控件、报表平台、DevExpress Dashboard eXpressApp 框架、适用于 Visual Studio的CodeRush等一系列辅助工具。屡获大奖的软件开发平台DevExpress 今年第一个重要版本v23.1正式发布,该版本拥有众多…...
基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险
C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...
