.NET Native:将.NET应用编译为原生应用
什么是.NET Native? .NET Native 是一套在Visual Studio 2015中编译通用Windows(UWP)应用的预编译工具,它可以将托管的中间语言二进制文件编译为本地二进制文件,每一个托管的通用Windows 应用都将受益于这项新技术。在用户设备上安装之前,应用会自动编译为原生代码。有关其工作机制的详情可以查看 MSDN 。
.NET Native会带来什么?根据不同的情况,.NET Native所带来的好处各种各样。不过在大多数情况下,.NET Native将会使得应用启动更快、运行更好、占用用户系统资源更少。具体优点如下:
- 冷启动效率提升60%
- 热启动效率提升40%
- 原生编译时应用占用内存资源更少
- 系统无需安装桌面.NET Runtime
- 由于应用在本地编译,性能可以借助原生代码的优势得到改善
- 可利用业内领先的C#或VB及其编程语言工具
- 提供全面而一致的.NET编程模型,包括编写业务模型所需的扩展API、内置内存管理以及异常处理等
Debug和Release两种编译模式的差异.NET Native的编译过程十分复杂,相比于传统的.NET编译,编译时间稍微长一些。上面提到的那些优点牺牲了一部分编译时间。Visual Studio在编译应用时会提醒开发者这一点,保证了良好的开发体验。
当使用Debug编译模式时,在应用中运行的是中间语言代码,.NET系统部件不和应用代码一起封装,而且应用需要依赖 Microsoft.NET.CoreRuntime (CoreCLR)包。这就意味着,开发者可以享有最优的开发体验。编译和配置都十分迅速,有着丰富的调试和诊断信息,在.NET开发中还可以使用所有熟悉的工具。
而对于Release模式,应用会默认使用.NET Native工具链。由于程序包编译成了本地二进制文件,它就不用再包含.NET框架库。另外,程序包依赖于最新安装的.NET Native Runtime而不是CoreCLR包,设备上的.NET Native Runtime始终与应用程序包兼容。
通过Release的本地原生编译可以在一个模拟用户使用的环境里对应用进行测试。在应用开发过程中,定期的测试十分重要,这样可以保证查找和修改.NET Native编译器相关的错误。大多数情况下.NET Native编译器会正常工作,但在少数情况下可能就不那么顺利了,比如4维以上的数组可能引发错误。用户最后获得的是.NET Native编译的应用,所以最好在开发过程中测试应用的版本,确认无误而后再发布。
另外需要补充的是,.NET Native取消了跨平台的编译模式。原生编译的架构独立,因此跨平台编译不再有用。一个附加的结果是,当开发者打包应用程序时,需要将三个体系结构配置(x86、x64、ARM)全部选中,以保证应用程序对所有的设备都能兼容。
.NET Native改变了打发布包的方式,这是给工作流带来的最后一个重大变化。.NET Native的一大特点是,编译器可以放置在云端。在Visual Studio中编译应用包时会创建两个包,一个是.appxupload文件,另一个是侧面加载用的“测试”.appx文件。.appxupload包含了MSIL二进制文件和应用使用的.NET Native工具链版本信息(也记录在了AppxManifest.xml文件中)。编译后的程序包接下来放入应用商店,然后被相同版本的.NET Native工具链编译。因为编译器置于云端,开发者无需在本地重新编译应用程序,便能够反复多次修改程序缺陷。
这样的改变给开发者工作流又带来了另外两个改变。第一是开发者不能修改应用程序包的第四个版本号,这是因为应用商店需要通过修改版本号来标记在云端的每一次编译行为。不过开发者还能修改其他三个 版本号 ,所以不必有太大的疑虑。第二是需要开发者特别注意上传到应用商店的程序包。应用商店代替开发者进行原生编译,所以开发者不能上传本地.NET Native编译器生成的原生二进制文件。对此,Visual Studio会帮助开发者选择正确的文件。
总结来说,.NET Native带来的最主要的变化是以下几点:
- 使用Release模式定期测试开发的应用程序
- 确保修订包编号为0(Visual Studio不允许修改,也不要使用文本编辑器修改)
- 只上传创建包时生成的.appxupload文件至应用商店。如果上传通用Windows平台的.appx文件,应用商店会拒绝并报错
使用.NET Native的其他小技巧如果开发者怀疑.NET Native造成了某些错误,可以尝试用以下方法解决。因为Release模式默认优化了代码,这会丢失Debug模式下需要的一些生成文件,所以在 Release模式中调试可能会出现错误。开发者可以新建一个自定义模式来使用.NET Native工具链,同时不要优化代码。详细内容可以查看 这里 。
从一开始就避免.NET Native相关的错误无疑是更好的选择。 Microsoft.NET Native.Analyzer 在开发过程中如果遇到代码与.NET Native冲突,会给出相应的警告。