What’s New in Windows Phone 8 (5 out of 8)–Quick tip: creating hybrid applications

November 5, 2012

One important feature in Windows Phone 8 is ability to develop high performance applications using Direct3D graphics and C++. While this feature clearly targets game developers, many applications could also gain performance combining native code with C++ components. Moreover, even when developing XAML/C# applications, it is possible to fully leverage modern GPU in Windows Phone 8 device by mixing XAML flexibility with Direct3D graphics.

Note: Pure native development using Direct3D are not covered in this post.

Let’s overview two other options: first is to use Direct3D graphics is XAML/C# application. Windows Phone 8 SDK provides very good starting point for such application:

image

Application created with this template combines standard Windows Phone 8 XAML application and WinRT native component. To integrate Direct3D surface into managed application, use new DrawingSurface XAML element. As standard XAML element it supports all standard XAML properties incl. Projection and RenderTransform and plays nicely with other XAML elements in layout. The following code snippet, for example, produce image below:

<Grid x:Name="LayoutRoot" Background="Transparent">

    <DrawingSurface x:Name="DrawingSurface">

        <DrawingSurface.Projection>

            <PlaneProjection CenterOfRotationX=".5" CenterOfRotationY=".5" CenterOfRotationZ=".5" 

                                RotationX="-30" RotationY="30" RotationZ="30"/>

        </DrawingSurface.Projection>

        <DrawingSurface.RenderTransformOrigin>

            <Point X=".5" Y=".5"/>

        </DrawingSurface.RenderTransformOrigin>

        <DrawingSurface.RenderTransform>

            <CompositeTransform Rotation="-25" ScaleX=".7" ScaleY="-1" TranslateY="20"/>

        </DrawingSurface.RenderTransform>

    </DrawingSurface>

    <Canvas>

        <TextBlock x:Name="textBlock" Text="Hello from Windows Phone 8!" HorizontalAlignment="Center" VerticalAlignment="Top" FontSize="25"

                    Canvas.Top="100" Canvas.Left="500"/>

    </Canvas>

    <Button Content="About" VerticalAlignment="Bottom" HorizontalAlignment="Center" Click="Button_Click_1"/>

</Grid>

image

The whole idea of this “mix” is very similar to hybrid Silverlight & XNA applications introduces back in Windows Phone 7.5.

The DrawingSurface is initialized with Windows Phone Runtime object that implements the IDrawingSurfaceProvider interface. The default templates provides sample of such component which implements 3D cube render. For more info please refer to documentation.

Second option available for developers is to integrate/reuse native code containing business logic with Windows 8 other other platforms. Also, in many cases integrating native code (especially for complex algorithmic manipulations) could add noticeable performance boost to application. Let’s see how to achieve this.

My sample application uses “heavy” math calculations as managed component:

namespace ManagedLibrary

{

    public class ManagedCalculator

    {

        public long Factorial(long n)

        {

           

            long nfac = 1;

 

            for (int i = 2; i < n + 1; i++)

            {

                nfac *= i;

            }

 

            return nfac;

        }

    }

}

As you see, this code calculates factorial for given number.

Note: the factorial calculation was not implemented as recursive function to be fully compatible with native code presented below.

The managed library used to calculate the factorials – let’s pretend it is a part of application’s business logic – as follows:

ManagedCalculator calc = new ManagedCalculator();

 

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();

 

long ticks = 0;

for (int j = 0; j < numOfTrials; j++)

{

    sw.Start();

    for (int i = 0; i < maxRuns; i++)

        calc.Factorial(rnd.Next(maxFactorialOf));

    sw.Stop();

 

    ticks += sw.ElapsedTicks;

    sw.Reset();

}

 

txtManaged.Text = "Average calculation time was " + ticks / numOfTrials + " ticks";

This code snippet invokes factorial calclation for fandom number given number of runs (maxRuns) for known number of trials (numOfTrials) and caluclates average runtime (in ticks).

Let’s have exact same functionality as managed WinRT component. To do it, we need to add new project and reference it from the applcation:

image

The header file for this component looks super simple:

namespace NativeLibrary

{

    public ref class NativeCalculator sealed

    {

    public:

        NativeCalculator();

        int64 Factorial(int64 n);

    };

}

And implemntation class is also very simple:

#include "pch.h"

#include "NativeLibrary.h"

 

using namespace NativeLibrary;

using namespace Platform;

 

NativeCalculator::NativeCalculator()

{

}

 

int64 NativeCalculator::Factorial(int64 n)

{

    long nfac=1;

 

    for(int i=2; i < n+1; i++)

    { 

        nfac *= i; 

    }

 

    return nfac;

}

Note, that factorial code is exact the same as in managed code.

Once native component is ready it could be referenced from main app:

image

and used as standard managed component:

NativeCalculator calc = new NativeCalculator();

 

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();

//Warm up run

calc.Factorial(10);

 

long ticks = 0;

for (int j = 0; j < numOfTrials; j++)

{

    sw.Start();

    for (int i = 0; i < maxRuns; i++)

        calc.Factorial(rnd.Next(maxFactorialOf));

    sw.Stop();

 

    ticks += sw.ElapsedTicks;

    sw.Reset();

}

 

txtNative.Text = "Average calculation time was " + ticks / numOfTrials + " ticks";

Note, that again, only difference is the type of created object.

Runnig this application reveals interesting facts – the bigger number we are trying to calculate factorial for, the bigger gain in performance we are getting with native code.

With maxFactorialOf = 10 the results are not in favor of native code:

image

If setting the maxFactorialOf = 100, the results are different and while still comparable, the native code clearly wins:

image

Setting maxFactorialOf = 1000 shows, that native is clearly faster – in this case almost twice faster than managed code:

image

Setting maxFactorialOf = 10000 allwos native code shine and beat native code completely:

image

Does it means, that all calculations (even smallest one) should be moved to managed code, just because it is faster? Not necessary. If you are migrating from another platform and have logic already written using native code then the answer probably yes (giving the fact, that native development not as easy as managed one). If you already using managed code your probably not necessary will gain major performance boost just by rewriting some of the business logic as native library. You could try, but “your mileage may vary”. One thing is for sure – it could introduce more bugs related to new native component.

 

That’s it for this post. Next time I will blog about location services and new map functionality.

 

Stay tuned,

Alex

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>