.NET Native - what does this mean for developers under the universal Windows platform (UWP)?

Original author: Daniel Jacobson
  • Transfer
In Windows 10, universal Windows-based applications in managed languages ​​(C #, VB) go through the store compilation process into machine code using .NET Native. In this article, we invite you to learn more about how it works and how it affects the application development process. Below you will find a video interview with a representative of the .NET Native development team and a translation of the related article.

What is .NET Native?

.NET Native is a pre-compilation technology used to create universal Windows applications in Visual Studio 2015. .NET Native tools compile your managed code IL libraries into native libraries. Each managed (C # or VB) universal Windows application uses this technology. Applications are automatically compiled into native code before they reach the end device. If you want to dive deeper into how this works, we recommend the article “ Compiling Applications Using .NET Machine Code ”.

How will .NET Native affect me and my application?

Specific indicators may vary, but in most cases your application will start faster, run faster and consume less system resources.
  • Up to 60% increase in cold start speed
  • Up to 40% increase in hot start speed
  • Reduced memory consumption when compiling to machine code
  • No dependency on the desktop .NET Runtime during installation

Since your application is compiled into machine code, you will get a performance gain related to the speed of native code execution (close to C ++ performance). However, you can still take advantage of the industrial programming languages ​​C # or VB and related tools.

You can also continue to use the full power of the programming model available in .NET with a wide range of APIs for describing business logic and with built-in memory management and exception handling mechanisms.
In other words, you get the best of both worlds: managed development with performance close to C ++. Isn't that great?

Differences in compilation settings in debugging and release

Compiling in .NET Native is a complex process, usually slower compared to classic compiling in .NET. The benefits mentioned above come at a price in the form of compilation time. You can choose to compile natively every time you launch the application, but you will spend more time waiting for the build to complete. Visual Studio tools can help you better manage this by smoothing out your development experience as much as possible.

When you build a project and run in debug mode, you use IL code on top of CoreCLR packaged in your application. .NET system assemblies are added to your application code, and your application takes into account dependency on the Microsoft.NET.CoreRuntime (CoreCLR) package.
This means that you get the best possible development experience: fast compilation and deployment, extensive debugging and diagnostics, and the performance of all other tools that you are used to when developing on .NET.

When you switch to release mode, by default, your application starts using the .NET Native build chain. Since the package is compiled into machine code, it is no longer necessary for the package to contain .NET framework libraries. In addition, the package now depends on the latest version of the .NET Native environment - unlike the CoreCLR package. The .NET Native runtime on the device will always be compatible with your application package.

Local native compilation with release configuration allows you to test the application in an environment close to what the end user will have. It is important to regularly test in this mode as you develop.

A good rule of thumb that you can get used to is to test your application in this way during the development process to make sure you find and fix issues that may result from compiling with .NET Native on time. In most cases, there should not be any problems, however, we know about a few things that do not work very well with .NET Native. For example, arrays with a dimension greater than four. In the end, your users will receive a version of your application compiled through the .NET Native, so it would be nice to check that everything works in advance and before the application is delivered.

In addition to being nice to test in native compilation mode, you can also notice that the configuration configuration of the AnyCPU assembly has disappeared. With the advent of the .NET Native, AnyCPU configuration no longer makes sense, since native compilation is architecture dependent. An additional consequence of this is that when you package your application, you need to select all three architecture configurations (x86, x64 and ARM) to ensure that your application will run on as many devices as possible. Still, this is a universal Windows platform! By default, Visual Studio is configured to build exactly as shown in the image below.

All three architectures are selected by default.

It is important to note that you can still build AnyCPU libraries and use the appropriate DLLs in your UWP application. These components will be compiled into binary libraries for the corresponding architectures specified in the project settings.

Finally, the last significant change in the familiar approach resulting from the switch to .NET Native is how you create packages for the store. One of the key features of .NET Native is that the compiler can work in the cloud. When you create a package for a store in Visual Studio, two packages are created: .appxupload for the store and “test” .appx for local installation. The .appxupload package contains MSIL assemblies, as well as explicit references to the version of .NET Native used by your application (specified in AppxManifest.xml). This package is then sent to the store and compiled using the same version of the .NET Native compilation chain. Since the compiler is in the cloud, it can be reused to fix bugs without having to recompile applications locally.

The .appxupload package is sent to the store; the Test folder contains the appx package for local installation.
Two consequences of this: first, as a developer, you no longer have access to the revision number of your application (fourth number). The store reserves this number as a way to version the application package, if for some reason recompilation in the cloud is required. Don’t worry, you can still control three other numbers .

The second thing you need to keep in mind is that you need to be careful about which package you upload to the store. Since the store compiles to machine code for you, you cannot load native assemblies created by the local .NET Native compiler. Visual Studio helps you figure this out so you can choose the right package.

Select “Yes” to upload to the store.

When you use the assistant to create application packages, you need to select “Yes” when asked by Visual Studio if you want to create a package to download to the store. I also recommend choosing “Always” for the “Generate app bundle” option, which will result in a single .appxupload file ready for download. Full instructions on creating packages for the store are available in the article “ Packaging Universal Windows Applications for Windows 10 ”.

As a result, the main changes in the way you work are from using .NET Native:
  • Test your app regularly in release mode.
  • Make sure you leave the package revision number as 0. Visual Studio will not let you change it, but you should not do this in other editors.
  • Only upload .appxupload collected during the creation of the package for the store to the store; if you download .appx for the UWP application, you will receive an error in the store.

Additional Tips for Using .NET Native

If you run into a problem for which you suspect .NET Native, there is a technique that can help you debug such a problem. The release configuration by default optimizes the code so that it loses some of the artifacts used in debugging. As a result, trying to debug the release configuration will be complicated. Instead, you can create your own configuration by allowing it to use .NET Native compilation. Make sure you are not optimizing the code. See the article “ Debugging .NET Native Windows Universal Apps ” for more information.

Now that you know how to debug problems, would it not be even better to learn how to avoid them? To do this, through NuGet, you can put Microsoft.NETNative.Analyzer into your application(From the package management console, you can use the “Install-Package Microsoft.NETNative.Analyzer” command). During development, the analyzer will warn you if your code is not compatible with the .NET Native compiler. There is a small subset of the .NET space that is not compatible, but most applications will never run into such a problem.

If you want to independently evaluate the improvements in download time from switching to .NET Native, you can measure them yourself.

Known issues and solutions

There are a few things to keep in mind when using the Windows Application Certification Kit (WACK) to test your applications:
  1. When you run WACK on a UWP application that has not gone through the compilation procedure, you will encounter a non-trivial problem. It looks something like this:
    • API ExecuteAssembly in uwphost.dll is not supported for this application type. App.exe calls this API.
    • API DllGetActivationFactory in uwphost.dll is not supported for this application type. App.exe has an export that forwards to this API.
    • API OpenSemaphore in ap-ms-win-core-synch-11-1-0.dll is not support for this application type. System.Threading.dll calls this API.
    • API CreateSemaphore in api-ms-win-core-kernel32-legacy-11-1-0.dll is not supported for this application type. System.Threading.dll calls this API.

    The solution is to make sure you create the packages correctly and run WACK on the appropriate package. Follow the build recommendations to avoid this problem.
  2. Applications on .NET Native that use reflection may fail in the Windows App Cert Kit (WACK) with a link to Windows.Networking.Vpn for correction. To solve the problem, add the following line in the rd.xml file and rebuild the package:
    < Namespace Name=”Windows.Networking.Vpn” Dynamic=”Excluded” Serialize=”Excluded” Browse=”Excluded” Activate=”Excluded” />

To summarize

All Windows users should benefit from using .NET Native. Managed applications from the store will start and run faster. Developers will be able to combine development experience in .NET in Visual Studio , and users will receive productivity gains from native code. If you want to tell us about your experience or wishes, use UserVoice . If you want to report an error, please fill out the information on Connect .

Also popular now: