Mobius 一个运行在 .NET Core 上的 .NET 运行时

一个 .NET 应用仅仅只是一块在 .NET 运行时上面运行的二进制代码。而 .NET 运行时只是一个能执行这项任务的程序。当前的 .NET Framework 和 .NET Core 运行时采用 C++ 编写,而 Mobius 是一个使用 C# 重写的 .NET 运行时,重写包括 JIT 编译和 GC 等,这些逻辑都将和 C++ 无关git

原文:Mobius – .NET runtime running on .NET Core – TooSlowExceptiongithub

我看到这个有趣的项目的时候就想试试安利一下你们,这个项目特别适合用来了解 GC (Garbage Collector 垃圾收集)和 JIT (Just-In-Time Compiler 即时编译器)的算法

让 C# 编写一个 .NET 运行时和编写一个运行在这个运行时上的 .NET 应用是否有可能呢?换句话是不要 Native 的本机代码或 C++ 代码,全部的代码都是经过 C# 编写是否有可能?这看起来是一个无穷的递归,用 .NET 写 .NET 的运行时运行在 .NET 的运行时上。这是否是就是将一个 .NET 运行时运行在另外一个 .NET 运行时上?算法

做者kkokosa决定开始试试水,这就是作 Mobius 运行时想法的缘由。这个想法听起来很奇怪,连做者都不抱指望在一个世纪内将这个想法投入使用。不过做者的想法是想要了解若是写出整个 .NET 运行时须要多少的代码量。同时做者也发现了其实这个想法的做用其实很小,即便想象如今有一个 NuGet 包在安装完成以后就能够添加到咱的应用上,此时的这个包就包含了完整的运行时代码,其实好像也不能作什么框架

原理

其实这个想法在其余的领域也有人尝试过,最著名的不过是 RVM —— 用 Java 编写的 JVM 虚拟机。虽然他须要使用 C 的引导启动,可是能作到本身托管本身,彻底由 Java 运行的虚拟机同时不须要其余的虚拟机。这看起来很是和做者想象的 Mobius 很是接近性能

这个想法不止做者一我的在想,其实也有小伙伴在 Github 上发布了一个 issus 说可否使用 C# 写 JIT 和 GC 的逻辑学习

基于这些考虑,能够看到开发 Mobius 的缘由以下:测试

  • 用于实验和研究的框架。使用 C# 和 .NET 编写的运行时,咱能够更简易和快速的了解整个原型,好比对 JIT 或 GC 模块的更改。咱可使用熟悉的语言如 F# 等去编写整个 .NET 的底层
  • 用于学习。在写这个框架或参与开发的时候,能够从里面学到不少运行时的作法。这也是能够用到不少现代化的 C# 特性的项目,使用更底层的 API 如 Span staclallock Unsafe 等
  • 提高性能。这显然是颇有争议的一点。在另外一个托管的运行时上面运行另外一个运行时看起来就和高性能没有关联。可是若是应用是热启动,那么意味着此时运行的代码生成质量能够依托对CPU的优化,能够达到比本机代码更好的性能。使用 C# 开发理论上可使用更加稳健的优化。一样用 C# 写 GC 也能有相同的提高
  • 用于玩闹。对于不少人来讲,例如德熙看着这个项目一步步搭建起来是十分有趣的

如上面说的,其实都不是很强的理由,为何要用 .NET 去写 .NET 运行时。大多数状况下,人们会认为使用 C++ 开发和使用 C# 开发不是对立的,二者的差异不是很大。做者很是赞成这个观点,这就是为何做者实际上是将这个项目当成一个玩具和实验的项目优化

先抛开是否有必要作这样的事情,请让咱想一想这个项目能够如何作编码

基本设计原理

首先,要理解的最重要的事情是 Mobius 仍然会将咱的应用程序编译为本地 Native 代码。以这种方式,最终应用程序将以(几乎)本机代码速度运行。不一样之处在于托管的基础设施,如 GC 和类型系统、JIT编译器是做为托管代码运行的。这意味着这些代码也被 JIT 编译设计

如上图,咱们有两层JIT构建的代码和底层实际运行时的本地 Native 代码。从图片看起来中间的这一层 .NET Core 基础设施的 Mobius 层是多余的。若是这一层是使用无分配对象的方式写的,那么不须要任何的 GC 方法。在预热以后,对 JIT 的调用也将会不多。这就容许咱假设在一个正常运行的应用程序中,大部分在 Mobius 层的内容都是通过了 JIT 编译优化完成以后运行的,这包括了经常使用的对 .NET Core 代码的 JIT 构建的代码,这将十分接近 .NET Core 的原生调用

从上面的图看,其实 Mobius 的多余仍是很明显。一个能够想的方法是在两个运行时之间共享基础设施

重写整个类型系统并非一件颇有趣的事情。咱们甚至能够考虑在 Mobius 中重用相同的 GC 垃圾回收,因此使用 Mobius 给 .NET 应用提供对象将看起来不错。虽然上面的方法请看起来不错,但依然存在两个问题:

  • 这大大减小了 Mobius 框架须要研究的功能。由于没有从新研究一遍 GC 和 JIT 算法,咱们将被迫考虑如何合并现有的技术
  • 在 .NET 运行时里面 JIT 和 GC 和类型系统都有比较大的耦合。除了在 Mobius 实现相同的机制以外没有其余方法,将会受限于当前的方法

基于这个缘由,做者认为 .NET Core 运行时应该只提供不多量的运行时服务给到 Mobius 框架,提供的服务主要只是调用 Jit 编译代码

当前状态

当前做者仍是试验可行性,正在作的是让最简单的 C# 应用能玩起来

private static int Main(string[] args)
{
   int num = 1;
   int num2 = 2;
   return num + num2;
}

经过一些可行性的测试,做者看到了曙光,应该是能作出来的。目前全部须要的机制都已就绪,包括:即便编译的基础支持,经过托管调用 JIT 代码,经过 JIT 代码调用 Mobius 框架。可是由于测试可行性的项目代码写的糟,还须要一点时间对代码进行重构,完善并实现大量的元数据处理,去掉一些硬编码值

如今这个可行性项目只是能作到运行当前这个简单的应用而已,运行的时候经过彻底的 CIL 指令和没有任何的异常处理,同时只有 GC 的存根

在下一篇系列文章中,做者将介绍Mobius实现最底层部分的更多细节和代码片断

逗比注:

若是本文看的不错,想要参与开发,我以为在这以前须要先读一下农夫的书,请看 《.NET 底层入门》这本书

另外上面说的玩具什么的只是原做者谦虚的说法,其实这个玩法是可行的,在 Github 有小伙伴在讨论,请看 Port JIT and GC to C# 这个连接

相关文章
相关标签/搜索