Writing a Xaml attached property in C++/CX to resize Images, with a Performance twist

By jay at February 04, 2013 21:41 Tags: , , , , , ,

TL;DR: Writing Xaml/C++ attached properties sometimes gives a 30% improvement over the C# version, which can be caused by the use of events. This article shows code sample for both versions.

 

 

Since it is possible to write a XAML application entirely in C++/CX, I decided to give a try to the performance of some simple code.

There is, after all, some marshaling involved when communicating from C# to native code, particularly with events.

 

The ImageDecodeSizeBehavior

WinRT’s BitmapImage class supports, as does WPF and Silverlight, the DecodePixelWidth and DecodePixelHeight properties.

These are very useful properties that forces the memory surface to store the image to fit a certain size, and avoid the waste of memory induced by large downscaled images. This is a very common performance issue for applications that display variable sized images, where the memory can grow very quickly.

More...

On the Performance of WinRT/Xaml Template Expansion

By jay at February 02, 2013 15:11 Tags: , , , , , ,

TL;DR: Expanding data-bound item templates in Xaml/WinRT in Windows 8 is about a hundred times slower than with Xaml/WPF. This article details how this was measured and a possible explanation.

 

In Windows 8, Microsoft has a introduced a whole new Xaml stack, codenamed Jupiter, completely re-written to be native only.

This allows the creation of Xaml controls using C++ as well as C#.

I will not discuss the philosophical choice of ditching managed WPF in favor of a native rewrite, but make a simple comparison of the performance between the two.

 

Template Expansion Performance

I worked on a project that had performance issues for a UI-Virtualized control, where the initial binding of data as well as the realization of item templates, was having a significant impact on the fluidity of the scrolling of a GridView control.

To isolate this, I created a simple UI: More...

DataBinding performance in WinRT and the Bindable attribute

By jay at November 26, 2012 20:51 Tags: , , , ,

tl;dr: The Bindable attribute can be placed on standard C# classes in Metro Apps to make them appear in the generated IXamlMetadataProvider class, to create static metadata. This technique allows for a 10% increase in data-binding performance over reflection based binding, but also adds a temporary cost in JITting, until Windows generates native images 24 hours later.

Databinding in WPF/WinRT is very easy to use. Just put the name of the field you want to bind, set the DataContext, and voila, it is displayed on screen. Yet, this is a tricky feature under the hood. It relies on the presence of an arbitrary string that may exist in the current DataContext to get the data to be displayed.

In WPF and Silverlight, this is fairly easy to do because everything is in managed code. Resolving that data member was performed using a bit of type Reflection, where the string "{Binding SomeValue}" would result in a sequence of Type.GetProperty to get a PropertyInfo instance, then call GetValue to get the actual value.

But in WinRT, all this is a lot different, mainly because WinRT is purely native and there is no reflection or metadata there.

More...

Xaml integration with WinRT and the IXamlMetadataProvider interface

By jay at March 07, 2012 21:04 Tags: , , , , ,

TL;DR: This article talks about the internals of the WinRT/Xaml implementation in Windows 8 and how it deals with databinding, its use of the IXamlMetadataProvider interface, tips & tricks around it, and how to extend the resolver to create dynamic databinding scenarios.

 

Xaml has been around for a while, and it’s been a big part of Silverlight and WPF. Both frameworks are mostly managed, and use a CLR feature known as Reflection, or type introspection.

This is a very handy feature used by Silverlight/WPF to enable late binding to data types, where strings can be used to find their actual classes counter-parts, either for value converters, UserControls, Data-Binding, etc...

 

The burden of .NET reflection

It comes with a cost, though. Reflection is a very expensive process, and up until very recently in Silverlight, there was no way to avoid the use of Reflection. The recent addition of the ICustomTypeProvider interface allows for late binding without the use of reflection, which is a big step what I think is the right direction. Having this kind of interface allows for custom types that define pre-computed lists of fields and properties, without having the runtime to load every metadata available for an object, and perform expensive type safety checks.

This burden of the reflection is particularly visible on Windows Phone, where it is suggested to limit the use of DataBinding, which is performed on the UI thread. The Silverlight runtime needs to walk the types metadata to find observable properties so that it can properly perfrom one or two-way bindings, and this is very expensive.

There are ways to work around this without having ICustomTypeProvider, mainly by generating code that does everything the Xaml parser and DataBinding engines do, but it’s mainly experimental, yet it gives great results.

 

WinRT, native code and the lack of Reflection

In Windows 8, WinRT is pure native code, and now integrates what used to be the WPF/Xaml engine. This new engine can be seen at the cross roads of Silverlight, WPF and Silverlight for Windows Phone. This new iteration takes a bit of every framework, with some tweaks.

These tweaks are mainly related to the fact that WinRT is a native COM based API, that can be used indifferently from C# or C++.

For instance, xml namespaces have changed form and cannot reference assemblies anymore. Declarations that used to look like this :

     xmlns:common="clr-namespace:Application1.Common"

Now look like this :

     xmlns:common="using:Application1.Common"

Where the using only defines the namespace to be used to find the types specified in the inner xaml.

Additionally, WinRT does not know anything about .NET and the CLR, meaning it cannot do reflection. This means that the Xaml implentation in WinRT, to be compatible with the way we all know Xaml, needs to be able to do some kind of reflection.

 

Meet the IXamlMetadataProvider interface

To be able to do some kind reflection, the new Metro Style Applications profile generates code based on the types that are used in the Xaml files of the project. It takes the form of a hidden file, named XamlTypeInfo.g.cs.

That file can be found in the “obj” folder under any Metro Style project that contains a Xaml file. To find it, just click on the “Show all files” button at the top of the Solution Explorer file. You may need to compile the project for it to be generated.

In the entry assembly, the file contains a partial class that extends the App class to make it implement the IXamlMetadataProvider interface. WinRT uses this interface to query for the details of types it found while parsing Xaml files.

This type acts as map for every type used in all Xaml files a project, so that WinRT can get a definition it can understand, in the form of IXamlType and IXamlMember instances. This takes the form of a big switch/case construct, that contains string representation of fully qualified types. See this example :

private IXamlType CreateXamlType(string typeName) 
{ 
  XamlSystemBaseType xamlType = null; 
  XamlUserType userType;

  switch (typeName) 
  { 
    case "Windows.UI.Xaml.Controls.UserControl": 
      xamlType = new XamlSystemBaseType(typeName, typeof(Windows.UI.Xaml.Controls.UserControl)); 
      break;

    case "Application1.Common.RichTextColumns": 
      userType = new XamlUserType(this, typeName, typeof(Application1.Common.RichTextColumns), GetXamlTypeByName("Windows.UI.Xaml.Controls.Panel")); 
      userType.Activator = Activate_3_RichTextColumns; 
      userType.SetContentPropertyName("Application1.Common.RichTextColumns.RichTextContent"); 
      userType.AddMemberName("RichTextContent", "Application1.Common.RichTextColumns.RichTextContent"); 
      userType.AddMemberName("ColumnTemplate", "Application1.Common.RichTextColumns.ColumnTemplate"); 
      xamlType = userType; 
      break; 

  } 
  return xamlType; 
} 

It also creates hardcoded methods that can explicitly get or set the value of every properties a DependencyObject, like this :

case "Application1.Common.RichTextColumns.RichTextContent": 
    userType = (XamlUserType)GetXamlTypeByName("Application1.Common.RichTextColumns"); 
    xamlMember = new XamlMember(this, "RichTextContent", "Windows.UI.Xaml.Controls.RichTextBlock"); 
    xamlMember.SetIsDependencyProperty(); 
    xamlMember.Getter = get_1_RichTextColumns_RichTextContent; 
    xamlMember.Setter = set_1_RichTextColumns_RichTextContent; 
    break;

Note that if you want to step into this code without the debugger ignoring you, you need to disable the “Just my code” feature in the debugger options.

Also, in case you wonder, the Code Generator scans for all referenced assemblies for implementations of the IXamlMetadataProvider interface, and will generate code that will query these providers to find Xaml type definitions.

 

Code Generation is good for you

Now, this code generation approach is very interesting for some reasons.

The first and foremost is performance, because the runtime does not need to use reflection to determine what can be computed at runtime. This is a enormous performance gain, and this will be beneficial for the perceived performance as the runtime will not waste precious CPU cycles to compute data that can be determined at compile time.

More generally, in my projects, I've been using this approach of generating as much code as possible, to avoid using reflection and waste time and battery on something that can be only done once and for all.

The second reason is extensibility, as this IXamlMetadataProvider can be extended to add user-provided types that are not based on DependencyObject. This is an other good impact on performance.

 

Adding custom IXamlMetadataProvider

It is possible to extend the lookup behavior for standard types that are not dependency objects. This opens the same range of scenarios that ICustomTypeProvider provides.

All that is needed is to implement the IXamlMetadataProvider interface somewhere in an assembly, and the code generator used for XamlTypeInfo.g.cs will pick those up and add them in the Xaml type resolution chain. Note that for some unknown reason, it does not work in the main assembly but only for referenced assemblies.

Every time the databinding engine will need to get the value behind a databinding expression, it will call the IXamlMetadataProvider.GetXamlType method to get the definition of that type, then get the databound property value.

A very good feature, if you ask me.

 

The case of hidden DependencyObject

By hidden dependency properties, I’m talking about DependencyObject types that are not directly referenced in Xaml files. This can be pretty useful for complex controls that generate convention based databinding, such as the SemanticZoom control, that provides a implicit “Key” property to perform the Zoomed out view.

Since this XamlTypeInfo.g.cs code is generated from all known Xaml files, this means that these hidden DependencyObject types that do not have code generated for them. This forces the CLR to intercept these failed requests and fallback on actual .NET reflection based property searching for databinding, which is not good for performance.

This fallback behavior was not implemented in the Developer Preview, and the binding would just fail with a NullReferenceException without any specific reason given to the developer.

 

The case of Xaml files located in another assembly

If your architecting a bit your solution, you’re probably using MVVM or a similar pattern, and you’re probably putting your views in another assembly.

If you do that, this means that there will not be any xaml file in your main assembly (aside from the App.xaml file), leading to an empty XamlTypeInfo.g.cs file. This will make any type resolution requested by WinRT fail, and your application will mostly likely not run.

In this case, all you need to do is create a dummy Xaml file that will force the generation of the XamlTypeInfo.g.cs, and basically make your layer separation work.

 

Until next time, happy WinRT'ing !

About me

My name is Jerome Laban, I am a Software Architect, C# MVP and .NET enthustiast from Montréal, QC. You will find my blog on this site, where I'm adding my thoughts on current events, or the things I'm working on, such as the Remote Control for Windows Phone.