大家好,
我发起并创立了一个 VMBC 的 子项目 D# 。
有关 VMBC , 请参考 《我发起了一个 用 C 语言 作为 中间语言 的 编译器 项目 VMBC》 https://www.cnblogs.com/KSongKing/p/9628981.html ,
D# , 就是一个 简单版 的 C# 。
下面说一下 D# 项目 的 大概规划 :
第 1 期, 实现 new 对象 的 机制, GC, 堆 。 (我做)
第 2 期, 实现 对象 的 函数(方法) 调用 。 (后人做)
第 3 期, 实现 元数据, 简单的 IL 层 基础架构, 简单的 IL 层 基础架构 主要 就是 元数据 架构 。 (后人做)
第 4 期, 实现 简单类型, 如 int, long, float, double 等 。 (后人做)
第 5 期, 实现 简单的 表达式 和 语句, 如 变量声明, 加减乘除, if else, for 循环 等 。 (后人做)
第 6 期, 实现 D# 代码 翻译为 C 语言中间代码 。 (后人做)
第 7 期, 实现 将 C 语言 代码 编译 为 本地代码 。 (后人做)
第 8 期, 各种 高级 语法特性 逐渐 加入 。 (后人做)
第 9 期, 各种 完善发展 …… (后人做)
我们来 具体 看一下 每一期 怎么做 :
第 1 期, 对象 的 new 机制, 就是用 malloc() 在 内存 里 申请一段 内存, 内存的 大小(Size) 是 对象 里 所有字段 的 Size 宗和, 可以用 C 语言的 sizeof() 根据 字段类型 取得 字段占用的 内存长度, 加起来 就是 对象 占用的 内存长度 。
GC, D# 的 GC 和 C# 有一点不同, C# 的 GC 会 做 2 件事 :
1 回收 对象 占用的 内存
2 整理 堆 里的 碎片空间
D# 只有 第 1 点, 没有 第 2 点 。 就是说 D# 只 回收 对象占用的 内存, 但不进行 碎片整理 。
C# GC 进行 碎片整理 需要 移动对象, 然后 修改 指向 这个对象 的 引用, 引用 是一个 结构体, 里面 包含了 一个指针, 指向 对象 的 地址, 对象 被移动后, 地址 发生了 改变, 所以 引用 里的 这个指针 也需要 修改 。
其实 不做 碎片管理 的 主要原因 是 碎片整理 的 工作 很复杂, 我懒得写了 。 ^^
碎片 整理 主要是 解决 碎片 占用了 地址空间 和 内存空间 的 问题, 以及 碎片 增多时 堆 分配 效率变低 的 问题 。
当然还有 碎片 占用了 操作系统 虚拟内存 页 的 问题 。
首先, 关于 碎片占用 地址空间 的问题, 现在 是 64 位 操作系统, 地址空间 可以达到 16 EB, 不用担心 地址空间 用完 。
内存空间 的 问题, 现在 固态硬盘 已经普及, 内存 也 越来越大, 固态硬盘 可以 让 操作系统 虚拟内存 很快, 再加上 内存 也 越来越大, 所以 也不用担心 内存空间 不够 的 问题 。
碎片 增多时 堆分配 效率变低 的 问题, 我们打算自己实现一个 堆算法, 下面会 介绍 。
碎片 占用了 操作系统 虚拟内存 页 的 问题 是指 碎片 占用了 较多 的 页, 导致 操作系统 虚拟内存 可能 频繁 的 载入载出 页, 这样 效率 会降低 。
这个问题 其实 和 碎片 占用 内存空间 的 问题一样, 固态硬盘 可以 让 操作系统 虚拟内存 很快, 内存 也 越来越大, 所以 基本上 也可以 忽略 。
另一方面, GC 整理碎片 移动对象 本身 就是一个 工作量 比较大 的 工作, 且 移动对象 时 需要 挂起 所有 线程 。
所以, 碎片整理 也是 有利有弊 的 。
D# 去掉了 GC 整理碎片 的 部分, 也可以说是 “空间换时间” 的做法,
另外, GC 工作时 不用 挂起 应用程序 线程, 可以 和 应用程序 线程 正常的 并发 运行 。
相对于 C#, 实时性 也会 好一些 。
原文地址:https://www.cnblogs.com/KSongKing/p/10348190.html