Mobius 一个运行在 .NET Core 上的 .NET 运行时
導(dǎo)語(yǔ)
一個(gè) .NET 應(yīng)用僅僅只是一塊在 .NET 運(yùn)行時(shí)上面運(yùn)行的二進(jìn)制代碼。而 .NET 運(yùn)行時(shí)只是一個(gè)能執(zhí)行這項(xiàng)任務(wù)的程序。當(dāng)前的 .NET Framework 和 .NET Core 運(yùn)行時(shí)采用 C++ 編寫,而 Mobius 是一個(gè)使用 C# 重寫的 .NET 運(yùn)行時(shí),重寫包括 JIT 編譯和 GC 等,這些邏輯都將和 C++ 無(wú)關(guān)
原文:Mobius – .NET runtime running on .NET Core – TooSlowException
https://tooslowexception.com/mobius-net-runtime-running-on-net-core/
我看到這個(gè)有趣的項(xiàng)目的時(shí)候就想試試安利一下大家,這個(gè)項(xiàng)目特別適合用來(lái)了解 GC (Garbage Collector 垃圾收集)和 JIT (Just-In-Time Compiler 即時(shí)編譯器)的算法
讓 C# 編寫一個(gè) .NET 運(yùn)行時(shí)和編寫一個(gè)運(yùn)行在這個(gè)運(yùn)行時(shí)上的 .NET 應(yīng)用是否有可能呢?換句話是不要 Native 的本機(jī)代碼或 C++ 代碼,所有的代碼都是通過(guò) C# 編寫是否有可能?這看起來(lái)是一個(gè)無(wú)窮的遞歸,用 .NET 寫 .NET 的運(yùn)行時(shí)運(yùn)行在 .NET 的運(yùn)行時(shí)上。這是不是就是將一個(gè) .NET 運(yùn)行時(shí)運(yùn)行在另一個(gè) .NET 運(yùn)行時(shí)上?
作者kkokosa決定開始試試水,這就是做 Mobius 運(yùn)行時(shí)想法的原因。這個(gè)想法聽起來(lái)很奇怪,連作者都不抱期望在一個(gè)世紀(jì)內(nèi)將這個(gè)想法投入使用。不過(guò)作者的想法是想要了解如果寫出整個(gè) .NET 運(yùn)行時(shí)需要多少的代碼量。同時(shí)作者也發(fā)現(xiàn)了其實(shí)這個(gè)想法的作用其實(shí)很小,即使想象現(xiàn)在有一個(gè) NuGet 包在安裝完成之后就可以添加到咱的應(yīng)用上,此時(shí)的這個(gè)包就包含了完整的運(yùn)行時(shí)代碼,其實(shí)好像也不能做什么
原理
其實(shí)這個(gè)想法在其他的領(lǐng)域也有人嘗試過(guò),最著名的不過(guò)是 RVM —— 用 Java 編寫的 JVM 虛擬機(jī)。雖然他需要使用 C 的引導(dǎo)啟動(dòng),但是能做到自己托管自己,完全由 Java 運(yùn)行的虛擬機(jī)同時(shí)不需要其他的虛擬機(jī)。這看起來(lái)非常和作者想象的 Mobius 非常接近
這個(gè)想法不止作者一個(gè)人在想,其實(shí)也有小伙伴在 Github 上發(fā)布了一個(gè)?issus?說(shuō)能否使用 C# 寫 JIT 和 GC 的邏輯
基于這些考慮,可以看到開發(fā) Mobius 的原因如下:
用于實(shí)驗(yàn)和研究的框架。使用 C# 和 .NET 編寫的運(yùn)行時(shí),咱可以更簡(jiǎn)易和快速的了解整個(gè)原型,比如對(duì) JIT 或 GC 模塊的更改。咱可以使用熟悉的語(yǔ)言如 F# 等去編寫整個(gè) .NET 的底層
用于學(xué)習(xí)。在寫這個(gè)框架或參與開發(fā)的時(shí)候,可以從里面學(xué)到很多運(yùn)行時(shí)的做法。這也是可以用到很多現(xiàn)代化的 C# 特性的項(xiàng)目,使用更底層的 API 如 Span staclallock Unsafe 等
提升性能。這顯然是很有爭(zhēng)議的一點(diǎn)。在另一個(gè)托管的運(yùn)行時(shí)上面運(yùn)行另一個(gè)運(yùn)行時(shí)看起來(lái)就和高性能沒(méi)有關(guān)聯(lián)。但是如果應(yīng)用是熱啟動(dòng),那么意味著此時(shí)運(yùn)行的代碼生成質(zhì)量可以依托對(duì)CPU的優(yōu)化,可以達(dá)到比本機(jī)代碼更好的性能。使用 C# 開發(fā)理論上可以使用更加穩(wěn)健的優(yōu)化。同樣用 C# 寫 GC 也能有相同的提升
用于玩鬧。對(duì)于很多人來(lái)說(shuō),例如德熙看著這個(gè)項(xiàng)目一步步搭建起來(lái)是十分有趣的
如上面說(shuō)的,其實(shí)都不是很強(qiáng)的理由,為什么要用 .NET 去寫 .NET 運(yùn)行時(shí)。大多數(shù)情況下,人們會(huì)認(rèn)為使用 C++ 開發(fā)和使用 C# 開發(fā)不是對(duì)立的,兩者的差別不是很大。作者非常同意這個(gè)觀點(diǎn),這就是為什么作者其實(shí)是將這個(gè)項(xiàng)目當(dāng)成一個(gè)玩具和實(shí)驗(yàn)的項(xiàng)目
先拋開是否有必要做這樣的事情,請(qǐng)讓咱想想這個(gè)項(xiàng)目可以如何做
基本設(shè)計(jì)原理
首先,要理解的最重要的事情是 Mobius 仍然會(huì)將咱的應(yīng)用程序編譯為本地 Native 代碼。以這種方式,最終應(yīng)用程序?qū)⒁?幾乎)本機(jī)代碼速度運(yùn)行。不同之處在于托管的基礎(chǔ)設(shè)施,如 GC 和類型系統(tǒng)、JIT編譯器是作為托管代碼運(yùn)行的。這意味著這些代碼也被 JIT 編譯
如上圖,我們有兩層JIT構(gòu)建的代碼和底層實(shí)際運(yùn)行時(shí)的本地 Native 代碼。從圖片看起來(lái)中間的這一層 .NET Core 基礎(chǔ)設(shè)施的 Mobius 層是多余的。如果這一層是使用無(wú)分配對(duì)象的方式寫的,那么不需要任何的 GC 方法。在預(yù)熱之后,對(duì) JIT 的調(diào)用也將會(huì)很少。這就允許咱假設(shè)在一個(gè)正常運(yùn)行的應(yīng)用程序中,大部分在 Mobius 層的內(nèi)容都是經(jīng)過(guò)了 JIT 編譯優(yōu)化完成之后運(yùn)行的,這包括了常用的對(duì) .NET Core 代碼的 JIT 構(gòu)建的代碼,這將十分接近 .NET Core 的原生調(diào)用
從上面的圖看,其實(shí) Mobius 的多余還是很明顯。一個(gè)可以想的方法是在兩個(gè)運(yùn)行時(shí)之間共享基礎(chǔ)設(shè)施
重寫整個(gè)類型系統(tǒng)并不是一件很有趣的事情。我們甚至可以考慮在 Mobius 中重用相同的 GC 垃圾回收,所以使用 Mobius 給 .NET 應(yīng)用提供對(duì)象將看起來(lái)不錯(cuò)。雖然上面的方法請(qǐng)看起來(lái)不錯(cuò),但依然存在兩個(gè)問(wèn)題:
這大大減少了 Mobius 框架需要研究的功能。因?yàn)闆](méi)有重新研究一遍 GC 和 JIT 算法,我們將被迫考慮如何合并現(xiàn)有的技術(shù)
在 .NET 運(yùn)行時(shí)里面 JIT 和 GC 和類型系統(tǒng)都有比較大的耦合。除了在 Mobius 實(shí)現(xiàn)相同的機(jī)制之外沒(méi)有其他方法,將會(huì)受限于當(dāng)前的方法
基于這個(gè)原因,作者認(rèn)為 .NET Core 運(yùn)行時(shí)應(yīng)該只提供很少量的運(yùn)行時(shí)服務(wù)給到 Mobius 框架,提供的服務(wù)主要只是調(diào)用 Jit 編譯代碼
當(dāng)前狀態(tài)
當(dāng)前作者還是試驗(yàn)可行性,正在做的是讓最簡(jiǎn)單的 C# 應(yīng)用能玩起來(lái)
private static int Main(string[] args)?
{
? int num = 1;
? int num2 = 2;
? return num + num2;
}
通過(guò)一些可行性的測(cè)試,作者看到了曙光,應(yīng)該是能做出來(lái)的。目前所有需要的機(jī)制都已就緒,包括:即使編譯的基礎(chǔ)支持,通過(guò)托管調(diào)用 JIT 代碼,通過(guò) JIT 代碼調(diào)用 Mobius 框架。但是因?yàn)闇y(cè)試可行性的項(xiàng)目代碼寫的糟,還需要一點(diǎn)時(shí)間對(duì)代碼進(jìn)行重構(gòu),完善并實(shí)現(xiàn)大量的元數(shù)據(jù)處理,去掉一些硬編碼值
現(xiàn)在這個(gè)可行性項(xiàng)目只是能做到運(yùn)行當(dāng)前這個(gè)簡(jiǎn)單的應(yīng)用而已,運(yùn)行的時(shí)候通過(guò)完全的 CIL 指令和沒(méi)有任何的異常處理,同時(shí)只有 GC 的存根
在下一篇系列文章中,作者將介紹Mobius實(shí)現(xiàn)最底層部分的更多細(xì)節(jié)和代碼片段
逗比注:
如果本文看的不錯(cuò),想要參與開發(fā),我覺(jué)得在這之前需要先讀一下農(nóng)夫的書,請(qǐng)看 《.NET 底層入門》這本書
另外上面說(shuō)的玩具什么的只是原作者謙虛的說(shuō)法,其實(shí)這個(gè)玩法是可行的,在 Github 有小伙伴在討論,請(qǐng)看?Port JIT and GC to C#?這個(gè)鏈接
https://github.com/dotnet/runtime/issues/10158
總結(jié)
以上是生活随笔為你收集整理的Mobius 一个运行在 .NET Core 上的 .NET 运行时的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 五分钟了解dotnetcore配置框架
- 下一篇: asp.net ajax控件工具集 Au