扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
这期内容当中小编将会给大家带来有关怎么理解.NET Native架构,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。
创新互联建站是创新、创意、研发型一体的综合型网站建设公司,自成立以来公司不断探索创新,始终坚持为客户提供满意周到的服务,在本地打下了良好的口碑,在过去的十年时间我们累计服务了上千家以及全国政企客户,如成都履带搅拌车等企业单位,完善的项目管理流程,严格把控项目进度与质量监控加上过硬的技术实力获得客户的一致夸奖。
这里简单讲一下.NET Native的基本架构,基本内容和上面那个talk其实差不多,只是简单给大家讲一下.NET Native的一些基本概念。
.NET Native和之前的NGEN有本质区别。NGEN实际上是把CLR运行时的数据结构和代码给一锅端(当然,这个是简化的说法,实际上比这个复杂)的放到最终的PE里面去了,运行的时候还是需要整个.NET Framework支持,而且不能避免JIT。.NET Native是全新的技术,整个.NET Framework经过refactoring重写,最终的runtime非常小,只有数百K,无需任何安装(除了mrt100.dll之外,大家可以理解成msvcrt.dll)。大部分的功能都从runtime中refactor到framework中作为C#代码或者作为toolchain一部分存在。一个典型的例子是:P/invoke原来是由CLR实现,使用C++和汇编编写。而现在是经由MCG这个工具接手,直接生成C#。最终.NET Native生成的EXE/DLL是可以直接运行的机器码(通过C++编译器后端生成)。对了,有些朋友可能会问:我们是不是直接生成C++代码?答案是否定的。我们所使用的C++编译器后端接受IL作为输入,生成MDIL。
整个Toolchain(工具链)大致可以分为下面几个阶段:
App IL + FX -> MCG -> Interop.g.cs -> CSC -> Interop.dll -> Merge -> IL transform -> NUTC -> RhBind -> .EXE
第一步:将应用程序的IL代码和整个.NET Framework BCL的IL一起作为输入给MCG。MCG (Marshalling Code Generator)这一块主要是我在负责。这个工具负责检查程序和BCL中所有的Interop相关的类型,比如WinRT接口,P/Invoke,等等。MCG都会为之生成C#代码。这个C#代码是可以直接调试的,有兴趣的朋友可以F11试一下看看。C#代码的作用主要是替代Windows.WinMD中的WinRT类型定义,P/invoke定义,等等,添加各种类型的转换代码,比如字符串类型,RCW和CCW,等等,最终直接调用到本地代码。可能有些朋友会问道:为什么要生成C#? 原来的CLR是直接在运行时生成IL代码的,但是显然这个方法在.NET Native不太适用,而且IL代码很难调试。C#既方便大家调试,也方便我们快速的修改生成的代码,添加更多的功能。(写C++程序生成IL代码可是比较麻烦的,得人工算好stack的位置)
第二步:MCG生成的C#代码通过CSC编译,生成PE文件。这一步没啥可讲的。
第三步:这个PE文件被打包合并到应用程序和BCL,生成一个IL代码的集合。为下一步做好准备。
第四步:这个IL代码的集合会被经过若干的步骤处理,每个步骤都相对简单,只做一件事情。这些步骤的主要作用是提供原来CLR运行时提供的功能,最终的目的是使之最后的代码能够被C++最后编译。在原来桌面版本的CLR里面(也就是4.5里面的那个),很多功能是由Runtime来提供,比如Delegate.Invoke,比如interop。这些Transform的作用是对代码进行处理,把原来需要runtime实现的部分用实际代码替换掉。举个几个例子:
1. 当你在调用Windows.UI.Xaml.Controls.Button类型的时候,MCG也会生成一个对应的Button类型,然后IL Transform会将两者进行替换,这样程序调用的Button类型就是MCG生成的代码了。
2. 当你在进行Serialization和Deserialization的时候,IL Transform会调用另外一个工具SG来生成serialization/deserialization的C#代码,最终这些操作都有这些C#代码生成。
3. 你的程序多半不会用到整个BCL。IL Transform中会有一步叫做Dependency Reducer,使用类似GC的算法(mark->sweep),去掉不需要的代码。MCG也和DR通力合作,减少不必要的interop代码生成。DR也会读取RD.XML文件,决定那些类型需要反射信息,那些不需要。RD.XML这一块我们还在改善之中,也希望大家多提宝贵意见。
其实呢,MCG其实也是IL Transform的一部分,只不过它实际上不Transform而已,而是直接生成C#。
第五步:NUTC对IL进行处理,生成MDIL。NUTC就是传说中的C++的编译器后端的一个特殊版本,优化什么的就靠它了。最后生成的MDIL接近机器码,但是也包含一些抽象的类型信息,需要进一步处理。
第六步:RhBind负责对MDIL进行处理,将里面和类型系统相关的信息生成代码,最后生成一个EXE。其实最终是一个EXE+DLL,实际的代码都在DLL中。EXE只是起到Bootstrap的作用。选用DLL的原因是我们需要支持作为Background Task在Broker里面加载。
几个我听到的常问的问题(如果有些答案过于“官方”,请谅解):
1. 你们最后是生成C++代码吗?
答:不生成。C++后端直接从IL转换成MDIL。
2. WPF支持吗?
答:暂时不支持。目前暂时只支持Windows Store Apps
3. 这个会支持桌面程序吗?
答:目前暂时只支持Windows Store Apps
4. 这个支持JIT吗?
答:目前.NET Native不支持JIT,所有代码都是编译时候生成。
5. 既然是本地机器码,为什么还可以支持类型反射(reflection)?
答:机器码和反射并不冲突,我们在PE文件中储存了额外的用于反射的信息,然后动态读取此信息进行调用。C++也可以支持反射(RTTI),只是不如.NET强大而已。
6.这个需要安装.NET Framework吗?
答:开发编译的时候需要,运行时不需要。
7.为什么不支持VB
答:VB本质上和C#都是生成IL,技术上非常类似。只是目前我们因为时间问题,暂只支持C#。
8.为什么启动运行速度会变快?
答:一方面归功于C++的优秀的编译器后端,一方面也因为runtime的重写和简化。
上述就是小编为大家分享的怎么理解.NET Native架构了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注创新互联行业资讯频道。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流