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# 這個連接

相關文章
相關標籤/搜索