`
hqs7636
  • 浏览: 215716 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

垃圾回收 2.014

阅读更多
无版本差异

D 是一种全面采用垃圾回收(Garbage Collection)的语言。这意味着它从来不用释放内存。只需要按需分配,然后由垃圾回收程序周期性的将所有未使用的内存返回给可用内存池。

C 和 C++ 程序员习惯于显式的管理内存分配和释放,很可能会怀疑垃圾回收的好处和功
效。对一开始就采用垃圾回收设计的新项目和用垃圾回收改良的现有项目的经验表明:

• 采用垃圾回收的程序更快。这有些违反直觉,但是其原理有:
• 引用计数是解决显式内存分配问题的常用解决方案。实现赋值时递增和递减操

作的代码通常是程序缓慢的原因之一。将其隐藏在智能指针类之后并不能提高
速度。 (无论如何,引用计数也不是全面的解决方案,因为循环引用从不会
被删除。)

• 析构函数用来释放对象获得的资源。对于大多数类来说,这个资源就是内存。
采用垃圾回收,大多数析构函数都可以完全抛弃。

• 当对象在堆栈上分配时,那些负责释放内存的析构函数就变得十分重要。对于
这些函数来说,必须确立一种机制以使异常发生时,每一个函数帧中的析构函
数都会被调用以释放对象持有的内存。如果析构函数变得不相关,就没有设置
特殊的堆栈帧用于处理异常,这样运行也会更快。

• 内存管理代码总量会变少。程序越大,它在cache中的部分的越少;它的调页
越多,它运行的越慢。

• 垃圾回收只会在内存变得紧张时才会运行。当内存尚且宽裕时,程序将全速运
行,不会在释放内存上花费任何时间。

• 相对于过去的缓慢的垃圾回收程序,现代的垃圾回收程序要先进得多。分代,
复制回收程序在很大程度上克服了早期的标记&清除算法的低效。

• 现代垃圾回收程序进行堆紧缩。堆紧缩将减少程序引用的页的数量,这意味着
内存访问命中率将更高,交换将更少。

• 采用垃圾回收的程序不会因为内存泄漏的累积而崩溃。

• 垃圾回收程序回收不被使用的内存,因此不会有“内存泄露”问题;内存泄露会使长
期运行的应用程序逐渐耗尽内存直至使系统崩溃。采用 GC 的程序拥有更长期的稳定
性。

• 采用垃圾回收的程序 有更少的难以发现的指针错漏。 这是因为没有指向已经释放的
内存的悬挂指针。因为没有显式的内存管理代码,也就不可能有相应的错漏。

• 采用垃圾回收的程序的开发和调试更快,因为不用开发、调试、测试或维护显式的释
放代码。

• 采用垃圾回收的程序会明显更小,因为没用用于管理内存释放的代码,也不需要处理
内存释放异常的代码。


垃圾回收并非什么仙丹妙药。它有着以下不足:
• 内存回收何时运行是不可预测的,所以程序可能意外暂停。
• 运行内存回收的时间是没有上界的。尽管在实践中它的运行通常很快,但无法保证这
一点。
• 除了回收程序以外的所有线程在回收进行时都会停止运行。
• 垃圾回收程序也许会留下一些本该回收的内存。在实践中,这不是什么大问题,因为
显式内存回收程序通常会泄露一些内存,这致使它们最终耗尽所有内存,另一个理由
就是显式内存回收程序通常会把内存放回自己的内部内存池中而不是把内存交还给操
作系统。
• 垃圾回收应该被实现为一个基本的操作系统内核服务。但是因为现实并非如此,就造
成了采用垃圾回收的程序被迫带着它们的垃圾回收实现到处跑。尽管这个实现可以被
做成一个共享 DLL ,它也还是程序的一部分。
这些限制可以通过采用 内存管理 中介绍的技术来缓解。


22.1 垃圾回收如何工作

GC 的工作方式:
1. 寻找所有在 GC 所分配的内存里的指针“根”。
2. 递归扫描所有分配的被“根”所指向的内存,查找更多在GC 分配内存内的指针
3. 释放所有没有激活指针指向的 GC 分配的内存。
4. 可能的话就通过复制分配的对象(叫做复制回收器)压缩余下被占用的内存。


22.2 外部代码同垃圾回收对象的协作

垃圾回收程序寻找根的地方有:
1. 它的静态数据段
2. 每个线程的堆栈和寄存器
3. 所有由 std.gc.addRoot() 或 std.gc.addRange() 添加的根
如果对象唯一的根不在它们中,回收程序将会释放它占有的内存。
要避免这种行为,则需要:
• 为对象维护一个根,该根要位于回收程序扫描的区域之内。
• 添加一个根到使用 std.gc.addRoot() 或 std.gc.addRange() 对象里。
• 使用外部代码的存储分配程序重新分配一个对象或者使用 C 运行时库的 malloc/free



22.3 指针和垃圾回收程序

D 中的指针可以被粗略地分为两类:指向垃圾回收内存的指针和其他的指针。后者包括由调
用 C 的 malloc() 所创建的指针,从 C 库中获得的指针,指向静态数据的指针,指向堆栈上
对象的指针,等等。对于这些指针,所有 C 中的合法指针的操作都可以应用其上。
但是,对于垃圾回收指针和引用,对指针的操作就有一些限制了。这些限制是不会造成太大
的缺陷,但却会使垃圾回收程序的设计灵活许多。
未定义行为(Undefined behavior):
• 将指针同其他的值进行异或,如同在 C 中在链表中用异或保存指针那种小技巧。
• 不要使用异或技巧交换两个指针的值。
• 使用类型转换和其他的小技巧将指针存储在非指针变量内。
void* p;
...
int x = cast(int)p; // 错误:未定义行为

垃圾回收器在构建根集(root)时不会扫描非指针类型。
• 利用特定的指针对齐的特点在低位或者高位存储 flag :
p = cast(void*)(cast(int)p | 1); // 错误:未定义行为
• 将可能指向垃圾回收堆的值转换为指针:
p = cast(void*)12345678; // error:未定义行为


复制垃圾回收器可能会更改这个值。
• 不要将不同于 null 的“魔数”存入指针。
• 不要将指针值写入到磁盘然后再从磁盘读入到内存。
• 不要使用指针值来计算 hash(哈希)函数。采用复制技术的垃圾回收程序可能会任
意地在内存中移动对象,这会使 hash 值失效。
• 不要依赖指针的顺序:

if (p1 < p2) // 错误:未定义行为
...

因此,再一次提醒,垃圾回收程序可能会在内存中移动对象。

• 不要给指针加上或者减去一个偏移量,不然结果有可能会导致指针指向垃圾回收程序
原来为对象分配的范围之外。

char* p = new char[10];
char* q = p + 6; // 正确
q = p + 11; // 错误:未定义行为
q = p - 1; // 错误:未定义行为

• 如果这些指针可能指向 GC 堆的话,请不要位移它们,如:
align (1) struct Foo
{ byte b;
char* p; // 位移(misaligned)指针
}

如果底层硬件支持位移指针,而且该指针从未用来指向该 GC 堆,则也可以使用它
们。

• 不要使用“一个字节一个字节的”内存复制方式来复制指针值。这样可能会导致中间
条件,到时就没有合法的指针了;而且如果 GC 在此种条件下暂停线程的话,那么它
就会搞乱内存。大部分的 memcpy() 实现是可以工作的,因为它的内部实现完成的
是以排列块大于或等于一个指针大小的方式进行的复制,不过由于 C 标准并不担保
此种实现,因此在使用 memcpy() 时应特别小心。
可靠且可以完成的事情:

• 使用联合共享指针的存储空间:
union U { void* ptr; int value }

• 如果存在指向垃圾回收对象对象内部的指针,就不必维护指向对象开始处的指针。
char[] p = new char[10];
char[] q = p[3..6];
// q 完全可以用来指向整个对象,不需要同时
// 保留 p 。

程序员可以不用指针完成大部分任务。D 提供的各种特征使得人们在决大多数情况下都不需
要显式地使用指针,这些特征包括:引用对象、动态数组和垃圾回收。提供指针的目的是成
功地同 C API 衔接并完成一些低级的工作。


22.4 与垃圾回收程序协作

垃圾回收程序并不能解决所有的内存释放问题。例如,如果保留了一个指向一大块数据的指
针,那么就算它再也用不到了,垃圾回收程序也无法回收这块空间。为了解决这个问题,一
个不错的实际操作就是:在某个对象不再使用时将指向它的引用或指针设置为 null。
这个建议只适用于静态引用或者嵌入到其他对象内的引用。它对于那些存储在堆栈上的引用
没什么意义,因为回收程序并不扫描栈顶之上的部分,并且新的堆栈帧总会被初始化。



22.5 参考
• Wikipedia
• GC 问与答
• 统一处理器——垃圾回收器技术
• 垃圾回收:自动的动态内存管理算法
分享到:
评论

相关推荐

    计算机专业Java专业课程实验+CRM客户关系管理系统设计学生课程实验.zip

    学生课程实验:大二计算机专业JAVA专业课的课程实验,设计一个CRM的客户关系管理系统,含项目源码、数据库、以及汇报PPT。 内容目录: ├── readme.txt ├── 基于Java的CRM客户关系管理系统的设计和实现数据库 │ └── crm.sql ├── 基于Java的CRM客户关系管理系统的设计和实现项目源代码 │ └── MyCrm.zip ├── 基于Java的CRM客户关系管理系统的设计和实现项目运行截图 │ ├── 主界面.PNG │ ├── 产品信息管理.PNG │ ├── 客户信息添加.PNG │ ├── 登录.PNG │ └── 角色管理.PNG ├── 视频 │ ├── 1CRM客户关系管理系统_项目的配置以及启动.url │ ├── 2CRM客户关系管理系统_工作桌面_信息中心_邮箱功能_客户管理_订单管理.url │ └── 3CRM客户关系管理系统_财务管理_产品管理_部门管理_岗位管理_数据回收站_权限管.url └── 论文 ├── 基于Java的现代数字化CRM客户关系管理系统答辩ppt.pptx

    node-v12.17.0-linux-arm64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    常见移动变现术语(mobile monetization).docx

    常见移动变现术语(mobile monetization).docx

    废物转运站:决策指南 垃圾转运站:决策指南

    废物转运站:决策指南

    冰蓄冷的一些资料.zip

    冰蓄冷的一些资料:包括系统的原理图,设计计算等

    8. Django 表单与模型

    配套资源

    【蓝桥杯嵌入式】第七届省赛 - 模拟液位检测告警系统

    开源 【蓝桥杯嵌入式】第七届省赛 - 模拟液位检测告警系统

    基于matlab-gmm-dtw的说话人识别源码.zip

    本代码是基于DTW(动态时间规则)算法以及GMM(混合高斯模型)进行的说话人识别的程序。 现在大部分的说话人识别模型是基于MFCC的混合高斯模型设计的,但基于此的识别方式会受说话人之间相互模仿的影响,所以增加了一种特征参数,基音周期。 基因周期包含了语音频率结构信息,不易模仿。同时若直接对高斯混合模型进行解混会使识别速度很慢,所以先用DTW再用GMM可以极大地缩减识别时间。 注意:此代码仅为说话人识别代码,如需进行语音文件录制请自行添加面。 为了使使用更加条理清晰,建议后续添加说话人按照freespeech中已经建成的文件夹为模板并分类存放说话人语音文件,将对应说话人的语音文件保存在对应的文件夹中。 此建议仅为使使用者更加条理清晰,语音文件也可直接存放在freespeech文件夹中。 确认电脑安装配置了voicebox后,直接运行test4.m文件,会出现gui界面,接下来的操作,根据界面提示进行即可。 重新训练数据库,可在上述运行界面中删除数据库后重新训练即可,也可只知删除部分人的数据。 程序使用许先建立数据库。录制的语音时间太长会使程序生成数据库和数据比对的时间加长,请耐

    Honeywell BR-310 条形码扫描器手册

    Honeywell BR-310 条形码扫描器手册

    QT6实现的附带文件传输协议的串口终端

    QT6实现的附带文件传输协议的串口终端 QT6实现的附带文件传输协议的串口终端

    unity开发入门教程.zip

    Unity是一个流行的跨平台游戏开发引擎,它允许开发者使用C#等语言创建2D和3D游戏。以下是一个Unity开发的基本入门教程: 1. 安装Unity 首先,你需要从Unity的官方网站下载并安装Unity Hub和Unity编辑器。Unity Hub是一个用于管理Unity版本和项目的工具。 2. 创建新项目 打开Unity Hub,点击“New”来创建一个新项目。选择你需要的Unity版本、模板(例如2D或3D)和其他设置。 3. 熟悉Unity界面 Unity的界面主要由以下几个部分组成: Hierarchy:显示场景中的所有游戏对象。 Project:显示项目的所有资源,如场景、模型、材质、脚本等。 Inspector:显示当前选中游戏对象的详细信息和属性。 Scene:显示当前场景的3D视图,你可以在这里编辑游戏对象。 Game:显示游戏运行时的视图。

    基于MobileFaceNet的静默活体检测系统的设计与实现python源码+项目说明+模型.zip

    基于MobileFaceNet的静默活体检测系统的设计与实现python源码+项目说明+模型.zip 1、代码 2、实验环境 Windows 10(64位) CPU:AMD Ryzen 7 5800H RAM:16G GPU:NVIDIA RTX3060 开发工具:IntelliJ IDEA以及PyCharm 相关配置及版本: Chrome 90.0.4430.212 SpringBoot 2.2.6 Java JDK8 MyBatis 2.1.1 Mysql 8.0.25 Python 3.8 pytorch 1.7.1 torchvision 0.8.2 numpy 1.18.5 tensorboard 2.4.1 pandas 1.2.3 cuda 11.0.2 cudnn 11.2 torch 1.8.1 torchvision 0.9.1 3、模型训练命令 python train.py 4、模型测试命令 python test.py 5、运行检测模块命令 python detect.py --source 0

    金融产品营销方案设计33.docx

    金融产品营销方案设计33.docx

    识别说话人的性别和估计说话人的年龄 Matlab+MatlabGUI+SVM源码.zip

    识别说话人的性别和估计说话人的年龄 Matlab+MatlabGUI+SVM源码.zip识别说话人的性别和估计说话人的年龄 Matlab+MatlabGUI+SVM源码.zip识别说话人的性别和估计说话人的年龄 Matlab+MatlabGUI+SVM源码.zip识别说话人的性别和估计说话人的年龄 Matlab+MatlabGUI+SVM源码.zip识别说话人的性别和估计说话人的年龄 Matlab+MatlabGUI+SVM源码.zip识别说话人的性别和估计说话人的年龄 Matlab+MatlabGUI+SVM源码.zip识别说话人的性别和估计说话人的年龄 Matlab+MatlabGUI+SVM源码.zip

    Mysql数据库实战教程&案例&相关项目

    MySQL数据库作为一个广泛使用的开源关系型数据库管理系统,它在Web开发、数据管理和企业级应用中扮演着重要角色。以下是对MySQL数据库实战教程、案例及相关项目的描述: MySQL数据库实战教程: 教程目的:教程旨在教授学习者如何高效地使用MySQL进行数据存储、查询、更新和管理。通过实战案例,学习者将掌握数据库设计、SQL语言的高级应用、性能优化等关键技能。 核心内容: 数据库设计:学习关系型数据库的设计原则,包括实体关系模型、规范化理论等。 SQL语言:深入理解SQL语句的编写,包括数据的增删改查(CRUD)操作。 数据类型与索引:掌握MySQL支持的数据类型以及如何设计索引以提高查询效率。 存储引擎:了解不同的存储引擎如InnoDB、MyISAM的特性及其适用场景。 性能优化:学习如何分析查询性能并进行优化,包括查询重写和数据库调优。 实战案例: 案例一:电商数据库管理:设计一个电商网站的数据库,实现商品展示、用户登录、购物车管理等功能。 案例二:金融交易系统:构建一个金融交易数据库,模拟交易记录的存储和查询,包括实时数据分析。 案例三:社交网络平台:开发一个社交网络

    b0900febba0972d39e8ab81732d7a34c.mp3

    b0900febba0972d39e8ab81732d7a34c.mp3

    Vision Transformer 网络对7种小麦叶片病害分类,包含训练权重和数据集、迁移学习

    1.网络使用的是Transformer 网络中的 ViT 模型 2.数据集是7分类的小麦叶片病害(水泡,褐色斑点) 3.网络训练的过程中,会对数据集的训练集图像求取灰度值的均值和方差,预处理处理包括随机裁剪、中心裁剪等等。网络初始化会自动载入ViT 官方的预训练权重(transformer网络收敛很慢,不经过预训练效果会很差,因此本篇代码自动载入) 4.train.py 会自动生成数据集类别的 json 文件,所以不需要自己定义。train.py 训练完成会生成训练集的loss、测试集的loss,训练集的accuracy、测试集的accuracy,并生成对应的曲线保存至run_results文件内。训练完成会计算训练集和测试集的混淆矩阵,计算召回率、特异度啥的 5.预测代码是predict.py,只需要将待预测的图像放在inference文件夹下,代码会自动将该文件下所有的图像进行预测,并在原图像左上角写入最大的前三个类别和概率 【如果想要训练自己的数据集,参考README文件】 【本项目测试了30个epoch,准确率为0.88,网络未收敛,加大轮次可以增加精度】

    惠普服务器安装说明

    惠普服务器安装说明

    python学习导航.txt

    python烟花代码

    node-v12.10.0-linux-x64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

Global site tag (gtag.js) - Google Analytics