原文链接:
https://www.infoq.com/articles/mono-xamarin-webassembly-net5/
Mono现状与未来: 从Xamarin到WebAssembly、Blazor及.NET 5
本文要点
- Mono项目始于2001年,是首个面向.NET应用程序的多平台、开源框架的项目。
- Xamarin和Blazor分别代表了微软在移动和Web应用程序方面的努力,它们都是基于Mono并由Mono提供支持的。
- .NET 5为用户提供了两种运行时选项:高性能的CoreCLR(用于服务器和桌面应用程序)和轻量级的Mono(用于移动设备和WebAssembly)。
- Mono仍然支持.NET Framework兼容模式,并且可以与所有Microsoft的.NET IDE一起使用。
- 尽管Mono已经是.NET的一部分了,但仍有一些开发工作要致力于改善Mono的运行时性能和垃圾回收器。
- 现在.NET Core可以与Mono并行安装了,因此可以一起演进语言和运行时。
去年,微软发布了它的计划,其中涉及.NET未来以及.NET 5的路线图。计划于今年年底发布下一个主要版本,该版本旨在提供一个基于.NET Core、.NET Framework、Xamarin及Mono最佳部分的多平台、开源框架和运行时。
微软从2014年开始向.NET开源发展,当时微软宣布.NET Core即将开源。然而,在此之前,.NET就已经有了一个名为Mono的开源计划。 Mono项目始于2001年,最初它主要致力于为Linux桌面应用程序建立一个.NET开发平台。第一次正式版本是在2003年发布的,此后该项目逐渐演进为在多个平台和操作系统上支持.NET。
Mono是由Xamarin从2011年开始开发的。自从该公司被微软收购,并在2016年发布.NET Core 1.0以来,Mono和.NET Core一直在并行开发。根据最新发布的版本,InfoQ采访了Miguel de Icaza(目前他就职于微软,是Xamarin的联合创始人,Mono项目的原作者),讨论了Mono的现状及其在.NET生态系统中的未来,以及Xamarin如何适合这种情况。
InfoQ:从技术上讲,.NET Core和Mono之间的主要区别是什么?
Miguel de Icaza: Mono是基于.NET Framework的,.NET Framework是作为Windows一部分发布的.NET大版本。经过多年的发展,Mono和.NET都可以应用在不同的环境中。在.NET领域中,这最终导致了.NET Core 3(这是所有未来工作和创新的基础)的发布,而.NET Framework是一个长期维护的版本,它将继续被修复和调整。 但不会有任何重大的创新。
在Mono的世界里,运行时演进为支持我们所谓的“移动配置文件”,它是API的一个精选子集,适用于平衡用户需求与降低独立运行时部署的需求。这是Xamarin .NET努力的基础,也是最近WebAssembly工作的基础。
使用.NET的不同场景以及使用它们的环境将开发人员必须使用的API集合分割开了。对于开发人员来说,没有一种简单的方法可以发布在所有平台上都可以工作的库二进制文件。
创建能够适用于所有不同环境的二进制库的愿望是创建.NET标准的推动力——一个API的通用界面,可以在所有不同版本的.NET上工作,无论是小型设备、移动系统,还是大型服务器。我们在这里所采取的方法是提出一套在所有平台上都可以平等使用的API。但这仍然意味着我们要维护库的不同实现。
让.NET的所有变体都能够相互操作的方法就是.NET Standard,.NET Standard的每个新版本中都添加了更多的API,所有运行时都能确保这些API是通用的。当今使用最广泛的API契约是 .NET Standard 2, .NET Framework、.NET Core、Xamarin和Mono都支持该标准。
新的.NET Standard 2.1版本引入了新的创新功能,但它们仅在Mono、.NET Core和Xamarin上可用,这是首个不被长期受支持的.NET Framework所支持的.NET Standard版本。
InfoQ: 考虑到.NET Core的最新成果以及.NET 5的路线图,Mono在当前状态的.NET生态系统中地位如何?
de Icaza: 简短的版本是,随着即将到来的.NET 5,用户将能够在所有平台上使用相同的API集合,并且可以选择运行时(CoreCLR或Mono)和编译系统(静态编译、JIT编译、分层或解释)来解决其问题的特定需求。
使用.NET 5,我们统一了类库的实现,同时为用户提供了两种运行时选项。在较高的层次上,在CoreCLR中具有一个高吞吐量、高性能的运行时,还具有一个轻量级(但速度没有那么快)的Mono运行时。每个运行时都已针对它们最常使用的工作负载进行了调整:CoreCLR用于服务器和桌面应用程序;Mono用于移动和轻量级应用程序,例如WebAssembly。
同样在.NET 5中,我们将有一个统一的运行时,它可以在我们支持的所有平台上执行C#或F#代码。在某些平台上,用户将能够选择他们想要使用的运行时,而在其他平台上,将只有一个运行时可以使用。例如,对于Windows上的桌面应用程序,只有CoreCLR运行时适用,而对于iOS,只有Mono运行时可用。
现在,从历史上看,Mono具有两种执行和代码生成引擎。一种是我们称之为“mini”的代码生成器,它可以非常快速地生成本地代码,但是没有进行很多优化。为了实现更好的优化,Mono过去一直都依赖LLVM优化编译器。 LLVM以牺牲编译时间为代价,产生漂亮的、最优的、完善的代码。
此外,Mono具有两种操作模式:一种是运行时在执行时动态生成代码(我们称之为JIT编译),另一种是运行时提前编译代码(基本上是静态编译)。提前(AOT)编译系统用于不允许动态代码生成的平台(例如iOS或视频游戏机),或者必须提高启动性能的平台(低端手机上的某些Android应用)。
Mono可以在纯JIT、混合AOT/JIT或AOT模式下运行,具体取决于平台的要求或用户的需求。因此,通常会使用LLVM提前编译一些核心库,例如,在保留用户代码可以动态编译(JIT)的情况下,为这些库生成最佳的代码。
需要纯AOT的系统有一个缺点,那就是.NET的动态功能不可用(例如,动态实例化类型、使用C# dynamic关键字、或动态加载代码等)。因此,我们着手解决这个问题。
去年,我们在Mono中引入了一个新的执行引擎和模式——一个解释器。事实证明,该解释器非常有用,这不仅是因为它能够带来动态性(以前缺少动态性),允许我们将一个小的运行时部署到WebAssembly,而且还能够使我们为用户带来一些“Hot”之类的功能,比如热加载和热重启。(注:这里重点关注下interpreter的进度)
一旦我们拥有三个具有不同配置的引擎,就有必要带来一个分层编译系统,该系统允许Mono运行时根据代码的使用方式动态调整要使用的代码生成引擎。并使用启动时间、内存使用率和长期性能。这是一个活跃的研究领域,我们也希望能够在该领域调整参数、学习或向用户提供解决方案。
.NET 5的好处在于,.NET 5的所有功能都可以在所有平台上使用,用户无需调整或更改任何内容。开箱即用的体验已经配置为全面匹配最佳可能的配置。
InfoQ: Xamarin和Blazor有什么区别?
de Icaza: Xamarin是我的初创公司,专注于帮助.NET开发人员实现移动化。我们使用Xamarin作为一系列产品的品牌,从开发工具到在线服务都使用该品牌。到目前为止,在线服务已被整合到Azure DevOps中了。
Xamarin开发工具包括原生SDK和Xamarin.Forms。原生SDK允许开发人员瞄准Android和iOS,并使用.NET平台中的所有原生功能。 Xamarin.Forms是一个跨平台的UI工具包,它使开发人员可以一次定义其用户界面,并将相同的代码映射成目标平台的本机习惯用法。
Blazor是一种通过C#构建交互式Web应用程序的新方法,它将一些最易于使用和最受欢迎的Web开发模式引入到了.NET。
开发人员可以构建Blazor应用程序,并可以选择逻辑运行的位置,它可以运行在由ASP.NET提供支持的服务器上,也可以完全运行在客户端上(为此,我们使用WebAssembly在浏览器内部运行一个.NET运行时)。值得注意的是,在WebAssembly上支持.NET的工作,当时是由Xamarin的Mono团队完成的,但是编程模型完全是由Blazor on WebAssembly开发团队构思出来的。 Mono只是提供了执行它们代码的方法。
InfoQ: 是否可以将Mono与其他微软的.NET IDE(Visual Studio、VS Code等)一起使用呢?
de Icaza: 当然可以。尽管大多数问题都是在展望.NET 5的未来,但是现在,在移动设备、Xamarin上构建支持.NET的应用程序,或构建针对WebAssembly的Blazor应用程序,Mono都是它们的引擎。这些功能在 Visual Studio和Visual Studio Code也是开箱即用的。
除了微软官方支持的配置之外,Mono(作为一个开源项目)仍然支持“ .NET Framework”兼容模式,并且可以与Mac上的Visual Studio或Linux上的MonoDevelop一起使用,以构建.NET Framework应用程序。 这的确是我业余时间做的一些工作,比如TensorFlowSharp、TorchSharp(PyTorch for .NET的绑定)和gui.cs(一个用户界面系统,可用于使用.NET构建文本用户界面)。
InfoQ: 还有一些其他与.NET Core相关的框架,比如EF Core、ASP.NET Core等。这些框架是否与Mono兼容呢?
de Icaza: 使用.NET 5,它们都是受支持的。在.NET 5之前,像ASP.NET Core之类的东西无法与Mono一起使用,这主要受限于与它相关的工具,而不是受限于运行时。
例如,EF Core是面向移动应用程序用户最喜欢的工具,它利用了.NET Standard,可以在Mono上开箱即用。
InfoQ: .NET生态系统中,Mono的未来是什么?
de Icaza: 现在,它已经从独立工作中毕业,逐步发展成为了整个.NET的一部分。现在.NET将会有一个单一发行版,该发行版会针对我们多年来积累的每个平台。我对开源社区多年来的支持工作感到非常自豪,也对我们团队持续集成这些VM的工作感到自豪。
现在出现了一些引人入胜的发展。例如,就在今天,在使用本地配置运行TechEmpower基准测试时,我看到使用静态编译和LLVM的Mono,现在可以与CoreCLR的性能相匹配了。
这对于Mono来说是一个重要的里程碑,因为当我们开始这项工作时,Mono离我们的目标还很远,甚至不在同一个球场上。但是,我们开始研究是什么导致了Mono的性能下降,分析并测量,直到我们找到了大多数的罪魁祸首,然后我们才到达这个位置。
Mono历来都有一个精确的垃圾回收器,该垃圾回收器轻量、高效, 适用于移动设备,但是对于这些拥有许多CPU和大型内存子系统的新计算机而言,它的扩展性却不佳。因此,我们现在有了一个使用CoreCLR GC的Mono的原型,这是一个针对Mono本身可高度扩展的GC。我希望我们将来能够为用户提供GC选项。
除此之外,世界看起来越来越像一个统一的VM,开箱即用地支持C#和F#,这是摆在我们面前最令人兴奋的工作。
到目前为止,将我们的语言和运行时一起演进是很困难的,因为演进运行时需要演进世界上每台Windows计算机上附带的运行时。为了避免回归共享框架(由许多用户共享),许多风险缓解流程已经就位,并且这些流程阻止了一体化进程中的大胆变革。
现在 .NET Core可以并行安装了,并且可以按照用户需要的频率进行升级,我们有了千载难逢的机会来共同演进语言和运行时,而且你已经可以看到其中的一些东西了。一些功能,例如接口中的默认方法实现,以及对整个类库进行改造以使其可为空引用,这是最近的一些开发,但是还有更多的功能有待开发,因此还会有很多机会将被解锁。
受访者简介:
Miguel de Icaza是一位微软的杰出工程师,专注于移动平台,他团队的目标是创建令人愉悦的开发人员工具。他与Nat Friedman于2011年共同创立了Xamarin,于1999年共同创立了Ximian。在此之前,Miguel在1997年与人共同创立了GNOME项目,并且自2001年Mono项目创建以来,他一直担任该项目的负责人,包括在Novell发行的多个Mono版本。 Miguel曾荣获1999年自由软件基金会自由软件奖、1999年MIT年度技术评论创新者奖,并于2000年9月被《时代》杂志评选为新世纪100名创新者之一。
Mono: from Xamarin to WebAssembly, Blazor, and .NET 5 - Q&A with Miguel de Icaza
Key Takeaways
- Started in 2001, the Mono project was the first initiative towards a multi-platform, open-source framework for .NET applications.
- Xamarin and Blazor represent Microsoft’s efforts on mobile and web applications (respectively), and both are based on and powered by Mono.
- .NET 5 provides two options of runtimes for users: the high-performance CoreCLR (for server and desktop applications), and the lightweight Mono (for mobile and WebAssembly).
- Mono still supports the .NET Framework compatibility mode, and it can be used with all of Microsoft’s .NET IDEs.
- While Mono is already a part of .NET, there are still developments focused on improving Mono’s runtime performance and garbage collection.
- Now that .NET Core can be installed in parallel with Mono, it is possible to evolve the language and runtime together.
Last year, Microsoft released its plans involving the future of .NET and the roadmap towards .NET 5. The next major release, scheduled for the end of this year, aims at providing a multi-platform, open-source framework and runtime built upon the best parts of .NET Core, .NET Framework, Xamarin, and Mono.
Microsoft’s movement towards open-sourcing .NET started in 2014, with the announcement that .NET Core would be open-source. However, much earlier than that, .NET already had an open-source initiative called Mono. Started in 2001, the Mono project was initially focused on establishing a .NET development platform for Linux desktop applications. The first official release was in 2003, and since then the project evolved towards supporting .NET in multiple platforms and operating systems.
Mono was being developed by Xamarin since 2011. Since the company’s acquisition by Microsoft and the following release of .NET Core 1.0 in 2016, Mono and .NET Core have been developed in parallel. In the light of the most recent releases, InfoQ interviewed Miguel de Icaza — currently at Microsoft, co-founder of Xamarin, and the original author of the Mono project — to talk about the current state of Mono, its future in the .NET ecosystem, and how Xamarin fits in this scenario.
InfoQ: Technically speaking, what are the main differences between .NET Core and Mono?
Miguel de Icaza: Mono was based on the .NET Framework — the big version of .NET that ships as part of Windows. Over the years, both Mono and .NET evolved to be used in different environments. In the .NET universe, this has culminated into the release of .NET Core 3 (which is the foundation for all future work and innovation), and the .NET Framework being the long-term maintained version that will continue to be fixed and tuned, but will not see any major innovation.
On the Mono side of the world, the runtime evolved to support what we called the “mobile profile,” which was a curated subset of the APIs that was suitable for balancing the needs of users with the desire to make deployments of self-contained runtimes small. This served as the foundation of Xamarin’s .NET efforts, and the more recent WebAssembly work.
The different scenarios where .NET was being used, and the environments where they were used, fragmented the set of APIs that developers had to target. There was no simple way for developers to publish binaries of libraries that would work the same across all platforms.
The desire to create binary libraries that would work on all the various environments is the driving force for the creation of the .NET standard — a common surface of APIs that would work across all the different editions of .NET, from tiny devices and mobile systems to large servers. The approach we took here was to come up with a set of APIs that were present and worked equally across all platforms. But this still meant that we were maintaining different implementations of the libraries.
The way that we got all the variations of .NET to interoperate with each other was the .NET Standard, each new version of the .NET Standard has added more APIs that all the runtimes ensure are available across the board. The most used API contract today is the .NET Standard 2 which is supported across .NET Framework, .NET Core, Xamarin, and Mono.
A new 2.1 version of .NET Standard brought in new innovative capabilities, but is only available on Mono, .NET Core, and Xamarin — this is the first version of .NET Standard that is not supported by the long-term supported .NET Framework.
InfoQ: How is Mono positioned in the present state of the .NET ecosystem, considering the latest efforts involving .NET Core and the roadmap to .NET 5?
de Icaza: The short version is that with the upcoming .NET 5, users will have the same set of APIs available across all platforms, and will have a choice of a runtime (CoreCLR or Mono) and compilation system (static compilation, JIT compilation, tiered, or interpreted) to address the specific needs of their problem.
With .NET 5, we are unifying the implementation of the class libraries, yet providing two options of runtimes for users. At a high-level, we have a high-throughput, high-performance runtime in CoreCLR, and we have the lightweight, (but not as fast) Mono runtime. Each runtime has been tuned for the workloads where they have been used the most — CoreCLR, for server and desktop applications, and Mono, for mobile and lightweight uses, such as WebAssembly.
Also in .NET 5, we will have a unified runtime that can execute your C# or F# code on all the platforms that we support. On some of the platforms, users will be able to choose the runtime they want to use, and on other platforms, there will be a single runtime to use. For example, for desktop applications on Windows, only the CoreCLR runtime is suitable, and for iOS, only the Mono runtime is available.
Now, historically, Mono has had two execution and code generation engines. One, we called the “mini” code generator, and it produced native code very quickly, but also without many optimizations. For better optimizations, Mono has historically relied on the LLVM optimizing compiler. LLVM produces beautiful, optimal, and polished code,at the expense of compilation times.
Additionally, Mono has two modes of operation: one where the runtime generates code dynamically as it is executed (what we call JIT compilation), and one where we compile the code ahead of time (basically, a static compilation). The ahead-of-time (AOT) compilation system is used on platforms where dynamic code generation is not allowed (for example, iOS or video game consoles), or when improved startup performance is a must (some Android apps on low-end phones).
Mono can either run in pure JIT, mixed AOT/JIT, or AOT mode, depending on the requirements of the platform or the desires of the user. So, it is common to compile some of the core libraries ahead of time using LLVM to get the best code generated for those, while leaving the user code to be compiled dynamically (JIT), for example.
One downside of systems that require pure AOT is that the dynamic capabilities of .NET are not available (things like instantiating types dynamically, using the C# dynamic keyword, or loading code dynamically). So we set out to solve this problem.
In the last year, we have introduced a new execution engine and mode into Mono — an interpreter. The interpreter has turned out to be very useful, both because it has allowed us to bring dynamism (that was previously missing), and allows us to ship a small runtime to deploy to WebAssembly, as well as enabling us to implement capabilities, like Hot Reloading and Hot Restarting, for some of our users.
Once you have three engines with different configurations, it makes sense to bring a tiered-compilation system — one that allows the Mono runtime to dynamically adjust which code generation engine to use, depending on how the code is being used — and use startup time, memory usage, and long term performance. This is an active area of investigation and one where we want to tune the parameters, the learning, or surface the knobs to users to do so.
The nice thing about .NET 5 is that all of the capabilities of .NET 5 are available on all the platforms — users do not need to tune, or alter anything. The out-of-the-box experience has been already configured to match the best possible configuration across the board.
InfoQ: What is the difference between Xamarin and Blazor?
de Icaza: Xamarin was my startup that was focused on helping .NET Developers go mobile. And we used Xamarin as a brand for a spectrum of products, from developer tools, to online services. The latter group has been mostly folded into Azure DevOps at this point.
Xamarin developer tools included native SDKs and Xamarin.Forms. The native SDKs allowed developers to target Android and iOS, and use every native capability of those platforms from .NET. Xamarin.Forms is a cross-platform UI toolkit that allows developers to define their user interfaces once, and have the same code be mapped to the native idioms of the target platform.
Blazor is a new approach at building interactive Web Applications with C# by bringing some of the easiest to use and most-loved patterns of web development to .NET.
Developers build their Blazor apps and have a choice of where their logic runs — it can run on the server, powered by ASP.NET, or it can run fully on the client (and to do this, we run a .NET runtime inside the browser using WebAssembly). It is important to notice that supporting .NET on WebAssembly was done by Xamarin’s Mono team at the time, but the programming model was entirely conceived by the Blazor on WebAssembly development team. Mono only provided the means of executing their code.
InfoQ: Is it possible to use Mono with other Microsoft .NET IDEs (Visual Studio, VS Code, etc.)?
de Icaza: Absolutely. While most of the questions are forward looking as to what will come in .NET 5, today Mono is the engine that powers .NET on mobile, on Xamarin, or when you build Blazor applications that target WebAssembly. These are supported out of the box on Visual Studio and Visual Studio Code.
In addition to the officially supported configurations from Microsoft, Mono (as an open source project), still supports the “.NET Framework” compatibility mode, and this can be used with Visual Studio for Mac or MonoDevelop on Linux to build .NET Framework applications — and it is indeed how I do some of my spare time work, like TensorFlowSharp, TorchSharp (a binding of PyTorch for .NET), and gui.cs (a user interface system for building text user interfaces with .NET).
InfoQ: There are other frameworks related to .NET Core: EF Core, ASP.NET Core, etc. Are these frameworks compatible with Mono?
de Icaza: With .NET 5, they are all supported. Before .NET 5, things like ASP.NET Core do not work with Mono, mostly due to the tooling around it, rather than being a limitation of the runtime.
EF Core is a favorite tool of users who target mobile applications, for example — and this leverages the .NET Standard to run on Mono out of the box.
InfoQ: What is the future of Mono in the .NET ecosystem?
de Icaza: It has now graduated from independent effort, into being part of the whole of .NET. And now .NET will have a single distribution that targets every single platform we have accumulated over the years. I am very proud of the work of the open source community that supported the effort over the years, and the ongoing work of our team to integrate these VMs.
There are some fascinating developments taking place now. For example, just today I saw that Mono, when using static compilation and LLVM, can now match the performance of CoreCLR when running the TechEmpower benchmarks on our local configurations.
This is an important milestone for Mono, because when we started this effort, Mono was ridiculously far off — it was not even in the same ballpark. But we started to look at what was slowing down Mono, profiling, and measuring until we found most of the culprits and we got to this place.
Mono has historically had a precise garbage collector that is suitable for mobile devices, lightweight and efficient — but does not really scale well for these new computers with many CPUs and large memory subsystems. So, we have a prototype now of Mono using the CoreCLR GC — a highly scalable GC for Mono itself. I am hoping that we will be able to offer a GC choice to our users in the future.
Beyond that, the world looks more and more like a unified VM, supporting both C# and F# out of the box, and that is the most exciting piece of work ahead of us.
Up until now, evolving our languages and the runtimes together has been difficult, because evolving the runtime required evolving the runtime that ships on every Windows computer in the world. To avoid regressing a shared framework (shared by so many users), many risk mitigation processes were in place, and those prevented bold changes in this integration from happening.
Now that .NET Core can be installed in parallel, and can be upgraded at the cadence that the users need, we have a golden opportunity to evolve the language and runtime together — and you are starting to see some of those things show up. Capabilities, such as default method implementations in interfaces, and retrofitting the whole class libraries to work with nullable references are some of the recent developments,but there is so much more in store, and so many opportunities that have been unlocked because of this.
About the Interviewee
Miguel de Icaza is a Distinguished Engineer at Microsoft focused on the mobile platform where his team’s goal is to create delightful developer tools. With Nat Friedman, he co-founded both Xamarin in 2011 and Ximian in 1999. Before that, Miguel co-founded the GNOME project in 1997 and has directed the Mono project since its creation in 2001, including multiple Mono releases at Novell. Miguel has received the Free Software Foundation 1999 Free Software Award, the MIT Technology Review Innovator of the Year Award in 1999, and was named one of Time Magazine’s 100 innovators for the new century in September 2000.