Udostępnij za pośrednictwem


Keep your app fast when you use interop (XAML)

The Windows Runtime makes interoperability easy, but if you're not careful it can incur performance costs. Here we show you how to get good performance when you use interop in your Windows Store app using C++, C#, or Visual Basic for Windows 8.

The Windows Runtime allows developers to write Windows Store apps using XAML with their language of choice thanks to the projections of the Windows Runtime APIs available in each language. When writing an app in C# or Visual Basic, this convenience comes at an interop cost because the Windows Runtime APIs are usually implemented in native code, and any Windows Runtime invocation from C# or Visual Basic requires that the CLR transition from a managed to a native stack frame and marshal function parameters to representations accessible by native code. This overhead is negligible for most apps. But when you make many calls (hundreds of thousands, to millions) to Windows Runtime APIs in the critical path of an app, this cost can become noticeable. In general you want to ensure that the time spent in transition between languages is small relative to the execution of the rest of your code. This is illustrated by the following diagram.

The types listed on .NET for Windows Store apps don't incur this interop cost when used from C# or Visual Basic. As a rule of thumb, you can assume that types in namespaces which begin with “Windows.” are part of the Windows Runtime, and types in namespaces which begin with “System.” are .NET types. Keep in mind that even simple usage of Windows Runtime types such as allocation or property access incurs an interop cost.

You should measure your app and determine if interop is taking up a large portion of your apps execution time before optimizing your interop costs. When analyzing your app’s performance with Visual Studio, you can easily get an upper bound on your interop costs by using the Functions view and looking at inclusive time spent in methods which call into the Windows Runtime.

If your app is slow because of interop overhead, you can improve its performance by reducing calls to Windows Runtime APIs on hot code paths. For example, a game engine that is doing tons of physics calculations by constantly querying the position and dimensions of UIElements can save a lot of time by storing the necessary info from UIElements to local variables, doing calculations on these cached values, and assigning the end result back to the UIElements after the calculations are done. Another example: if a collection is heavily accessed by C# or Visual Basic code, then it is more efficient to use a collection from the System.Collections namespace, rather than a collection from the Windows.Foundation.Collections namespace. You may also consider combining calls to Windows Runtime components; one example where this is possible is by using the Windows.Storage.BulkAccess APIs.

Building a Windows Runtime component

If you write a Windows Runtime component for use in apps written in C++ or JavaScript, make sure that your component is designed for good performance. Your API surface defines your interop boundary and defines the degree to which your users will have to think about the guidance in this topic. If you are distributing your components to other parties then this becomes especially important.

All of the suggestions for getting good performance in apps apply to getting good performance in components. Measure your component to find out which APIs have high traffic patterns, and for those areas, consider providing APIs that enable your users to do work with few calls. Significant effort was put into designing the Windows Runtime to allow apps to use it without requiring frequent crossing of the interop boundary.