Let’s get a bit creative this week.
I have this vision in my head of a wall of glittering sequin’s, you know what a sequin is right?! like what was big in the ‘disco’ era, and still is big today ?!..
For this post I want to start out simple and create a basic shimmering wall of sequins , nothing too complex!
My ulterior motive for doing this is to compare , what I’m guessing will be, GPU/CPU intensive animations between Silverlight 5 & WinRT XAML.
SILVERLIGHT 5 Approach
Let’s first do this in Silverlight …
STEP 1 : create a ‘sequin’ control.
Starting with Blend I visually drag a couple of ellipses and a rectangle for the background. And to add interaction there’s a “Storyboard”
There are basically 3 UI elements in the visual tree for an individual sequin. The storyboard gives the sequin it’s glitter effect.
NOTE : It’s important to point out that this process was a 100% visual task. With a “designer” hat on I would tweak gradients, pixel position vectors, add new visual elements as I saw fit. If I were in a different mood I may have made 6 UIElements, or maybe 12 , it all depends on my mood and how detailed I wanted to go. I’ll come back to this point later !!! ….
Step 2 : Create a wall of sequin’s
Taking the sequin control from above I layout hundreds of these elements to form a wall. To this was simple, I created new control “scr_Board” and used the “WrapPanel” layout control to wrap hundreds of these ‘sequin’ controls. I did the creation of the sequin’s in code and it’s not clean code, this is a demo after all
I did say that the code was not very pretty right .. Yes that is me calling into the sequin control from the board control setting & starting the storyboard animations for the sequin.. … I don’t recommended you do this in your projects, i’ve done it to make a point that I will come back to later in this post!!
So I’m creating 2584 sequin instances and loading those in the WrapPanel then starting the storyboard animation to initiate the glitter like effect for each sequin.
Also in the code you see me setting storyboard parameters with random values, that gives the random glitter effect..
Below is a quick video clip of the Silverlight 5 demo running.
Step 3 : Performance Tune the xaml
The hardest part of building solutions is tuning it for performance. And for something that is visually rich and uses a lot of animations you NEED to do A LOT of tuning.
There are 2514 sequin’s controls that are all animating individually. And this is a very simple demo. This is how this non-optimized solution performs. That’s around 74% CPU , 115MB Memory Consumed
Now let’s start playing with CacheMode, dictating to the GPU what surfaces to combine etc. So setting it at the root of the sequin visual tree, this is the performance improvement we get… That’s around 51% CPU , 156MB Memory Consumed
Because the visual tree for a sequin is very simple, 4 elements in all, I’m going to go ahead and set CacheMode on each and show you the results..
I normally wouldn’t’ go through every permutation of visual element and set the CacheMode on them…
The process I take is go through the visual tree and work out what makes sense to combine as a surface on the GPU and set the CacheMode on those. It may require me to tweak the visual tree by moving elements around and/or removing non-necessary ones. Also bare in mind if particular visual elements are involved in animations and are often changed then they probably don’t qualify to be cached.
This goes back to what I said earlier around how the UI was created by a designer like person using a visual tool like cider or blend. It’s easy to create very deep visual trees BUT as we can see above if we want a very performant application we need to take care with the design of the visual tree, OR spend time refactoring it before deploy.
So the best we can get is around 48% CPU with 160Mb MEM footprint. I won’t argue with you that 48% is terrible …. There’s more we can do to bring that down especially with how we animate and call storyboards, or our actual design of the storyboards.. The ultimate solution would be to go with “immediate mode” rendering using the XNA API … I will definitely do this in a future POST!!!
WinRT XAML Approach
Let’s now take the Silverlight app and port it to WinRT XAML …
STEP 1 : create a ‘sequin’ control.
Taking the SL5 seqin control to WinRT I discover that there was no “RadialGradientBrush”.
I tried creating my own “RadialGradientBrush”, extending the ‘GradientBrush’, BUT I kept getting XAMLTypeInfo COM exception errors when I tried referencing my custom class in xaml …
I believe the issue is related to this reported bug by Andy Beaulieu – “XamlTypeInfo.g.cs Generation Error”
In the end I had to settle for a “LinearGradientBrush”, ill revisit this when Beta arrives .
Step 2 : create a wall of sequins
There is no WrapPanel in WinRT so I took a Silverlight one and directly ported it over. Worked first go, nice and easy. I found the code on CodeProject .
Another issue I found was that ‘x:name=[name]’ elements in a control were no longer accessible from a parent control because the logic around ‘Protection levels’ has changed. eg. My sequin controls that had Storyboards and DoubleKeyAnimations defined could no longer be set/called from the parent. This is a great thing in my opinion
Another issue that arose was around DependencyProperties.Register() and it takes strings rather than types. This has been fixed and hopefully we’ll get these changes in beta very soon! (below is a screen shot of the issue I just mentioned above around DependencyProperty)
So here ‘s a quick video of the SL5 app converted to WinRT XAML with the few changes mentioned above.
What you’ll notice is that there appears to be a long pause on the black screen after the splash screen loads, that’s when the 2584 sequins are being dynamically created, initialized and added to the WrapPanel. I need to investigate this, as I mentioned this was just a simple port over from SL5 to WinRT XAML.
Also what’s not clear from the video is how buttery smooth the xaml metro app runs as you move between other metro apps and desktop. It is infinitely smoother than the Silverlight app running with other desktop apps, I can definitely say that the GPU acceleration of metro style apps is having a positive impact on performance
Another annoying issue that popped up is whenever I closed the app and killed it manually, there would always be an orphaned process created. There are so many of these weird issues popping up in this developer preview of Win8, and as a developer you will see a serious amount of these!
Another issue that popped up is that sometimes the app process would stay in the “Background Processes” section of the Task Manager and sometimes it would correctly appear in the “Applications” section.
Step 3 : Performance tuning
WinRT XAML also has CacheMode, you can set UIElement’s to be “HardwareBitmapCached” or “SoftwareBitmapCached”
Without any tweaking the CPU usage is at around 45% and the Memory around 130MB.
With tweaking I can get the CPU down to 30-35% and Memory to around 105MB
I know that that’s still a lot of % CPU , and I doubt the Windows Store would let any app that behaved as such BUT in my eyes that is brilliant that it can get to 30 in the first place. There is a lot of CPU draining code in there, and as I mentioned previously this type of animation is screaming to be done using a retained mode solution, XNA/DirectX …. Hopefully we’ll get that in Beta
What is a worry is that when the metro app is pushed to the background, it’s still running & consuming resources excessively. It appears that I the APP maker would need to detect this move to the background and carry out my own code to stop my app . It makes sense that I would need to do this HOWEVER a very small part of me would have wished that maybe MS could have added performance tuning smarts around storyboards and stopped running ones when a metro app goes into the background . That’s why I chose to put all animations in storyboards because technically they lend themselves to being better tooled, tweaked, analyzed & orchestrated etc. by the CLR and or the OS . I hopped that the platform could do smart things to them at the appropriate time, BUT I thought wrong! (picture below is the metro glittering sequins demo app running in background for over 15 minutes)
Another very interesting issue that came up with WinRT compared to Silverlight is that animations seemed to run so much faster in WinRT. I had to slow things down just to get comparable glittering
You can definitely achieve great results with Silverlight 5 if you take care with your visual tree and know how to optimize and use the provided tooling to debug/trace performance issues.
BUT WinRT definitely is showing signs of being an amazing GPU Accelerated framework that let’s you achieve levels of performance greater than anything Silverlight can offer today. And that’s not to say that Silverlight is bad, it’s all about using the right technology for the job.
If I were to build a client solution I would do this using an immediate mode approach, XNA or DirectX. Hopefully I’ll do just that in a future post
Let’s end with the glittering sequins again .. this is it again in WinRT ( I should point out that the UX definitely suffers because it’s using a LinearGradientBrush instead of a Radial one, yes those things make a huge difference . And it’s so much smoother when running as the video I took dropped frames hence the glittering is very jittery )
From now on all my future post’s will have an element of creativity in them, I have to get back to my roots
[UPDATED – 22nd January 2012]
As some of you have rightly pointed out, the code changed in the Win8 WinRT XAML version for the sequin, i.e. using a “LinearGradientBrush” instead of a “RadialGradientBrush”, will have an impact on performance in the Silverlight version. This is definitely true and i have run a simple test to see what difference this makes …. The improvement was around 2-4% reduction in CPU BUT the MEMORY pretty much stayed the same.
When I removed a whole “Ellipse” from the visual tree this reduced the MEMORY footprint by around 30-40MB .
Where Windows 8 WinRT-XAML definitely out performs sis when you are moving between apps and windows, it’s seriously buttery smooth.
All eyes are now on Windows 8 Beta