Silverlight Hack

Silverlight & related .NET technologies

About Me

Welcome to Silverlighthack.com.  This is a site where you can find many articles on Silverlight, Windows Phone 7 and .NET related technologies.  

My name is Bart Czernicki.  I have been working with computers since 1988 and have over 12 professional years in the IT field focusing on architecture, technology strategy and product management.  I currently work as a Sr. Software Architect at a large software development company.

Below is the cover of my new book that shows how Silverlight's unique RIA features can be applied to create next-generation business intelligence (BI 2.0) applications.

Silverlight 4 Business Intelligence Soft 

Contact: bartczernicki@gmail.com

View Bart Czernickis profile on LinkedIn

NONE of the comments or opinions expressed here should be considered ofmy past or current employer(s).  The code provided is as-is without anyguarantees or warranties.

Silverlight 2 RC0 - Important & Less Obvious things developers need to know

Silverlight 2 RC0 is released to the public.  Yay!   With this release, there are a lot of changes to the way Microsoft is doing things and behind the scenes (if you read into some of the posts) how things are going to shape up for the RTM release.  So after reading a lot of information and playing with RC0, I decided to write a small article on what is important in this release for developers.  I am not trying to rehash what other posts said, but focus on the main & important issues every Silverlight developer should know about the RC0 release.

Silverlight 2 RC0 is a Developers release ONLY

There is no non-developer runtime that is available for public deployments.  Before you go off and uninstall Beta 2, make sure you understand the ramifications of this.  RIA shops who are building Silverlight applications and have client demos or betas for clients SHOULD keep Beta 2 installed.  RC0 should be used for developer testing and getting ready for RTM.  The entire purpose of this release is just to get developers ready for Silverlight.

RC0 is "feature complete"

If you were hoping for a certain feature inside Silverlight, give RC0 a run.  Most likely if it is not in RC0, it will not be there in Silverlight 2 RTM.  For example, the two biggest features on my wishlist for RTM were: WS compliant WCF binding support and printing.  Both of these will not be in RTM version.  The nice thing is they are done adding features and changing stuff on developers.  However, the downside is that some of the features people were hoping for are not in this release cycle.

Still no official Silverlight 2 RTM release date

Microsoft has updated their release date for Silverlight 2 RTM for "later this year".  I don't know if this means Novemeber (PDC, Devconnections) or December.  However, that date could slip.  Earlier this year Microsoft was targeting a "late summer" release for Silverlight 2 RTM.  With RC0 being a "developer only" release, you need to plan your development accordingly.  This might include continuing with Beta 2 while keeping in mind the breaking changes so that your upgrade path to RTM is easy.

What is going on with Expression Suite (Blend) ?

Those who have been working with Silverlight for a while will note that with each Silverlight Beta release Microsoft released a new update to Expression Blend 2.5.  Since the RTM release is almost upon us, Microsoft has given us insight on the version of Blend that will work with Silverlight 2 RTM.  Blend 2.0 + SP1 will work with Silverlight 2 RC0 and eventually Silverlight 2 RTM.  The nice point there is that those that invested in Expression Blend 2.0 several months ago will not have to upgrade to a new version and simply will have to download the SP1 upgrade.

For those that have not purchased the Expression 2.0 Studio or Blend 2.0, it might be a good time to purchase it or plan for it in your budget.  If you do not have Expression Blend 2.0, you can:

I would recommend purchasing the Expression Professional Subscription if you do not already have an MSDN subscription and are looking to get the best value.  For $999, you get the Expression Studio 2 (699) and Visual Studio/Office/Vista, etc.  So for $300 more, you get a lot more Microsoft developer licenses.

Base Controls and additional controls

Silverlight RC0 adds a few more controls to the Silverlight 2 gallery: ComboBox, Password text box and a progress bar.  That is all the controls you should expect to see inside Silverlight 2 RTM. However, Shawn Burke a couple of weeks ago gave some additional insight on additional controls that are going to be added.  The Silverlight controls are going to be released in a similar model in which the AJAX Control Toolkit was released:

  • Controls will be posted on CodePlex (source code available)
  • They will have frequent releases (every 2 months)
  • Once the controls get baked and are heavily requested by customers, they might make it into the Silverlight Core product

This is very cool news!  Since the release cycle of Silverlight 2 (going back to Silverlight 1.1 Alpha last year) has been pretty long, it would suck if Microsoft didn't adopt his add-in model.  This is going to work out really great because it will allow the community to participate in some of the innovation of the controls and possibly speed up adoption inside Silverlight.  Plus, you get to learn from the best on control development.

Look and feel upgrade(s)

Scott Guthrie outlined in his latest article the improved look and feel for RC0 and the RTM release.  There have been additional themes released by individuals that were pretty cool but not always complete.  Scott mentioned that after the RTM release, there will be additional themes made available for Silverlight.  Hopefully this has some additional integration with Blend.   This is pretty positive news (the same way that Microsoft will add more controls after the RTM release) Non-designers don't have to struggle to create their own or rely on just third party themes.  Hopefully that is released seamlessly into the Silverlight or Expression Suite stack.

Silverlight 2 Client Runtime

Microsoft confirmed that when Silverlight 2 RTM ships, all the client runtimes will automatically upgrade to Silverlight 2 RTM from Silverlight Beta 1/2.  Once your product is ready to ship, you should be okay.  However, you want to make sure the release date coordinates with your product release.  As the runtime updates are controlled by Microsoft, your product might stop working.  Plan accordingly.

Silverlight 2 Best Practices

With RC0 and RTM probably around the corner, the codebase is pretty much done.  Now you will have a flurry of articles from the Microsoft team, MVPs and others on how best to implement certain features using Silverlight 2 RTM.  For example, printing is not available but this does not stop you from using the HTML access inside Silverlight.  Furthermore, using the MVC design inside Silverlight will become a little more refined.  Other "tips and hacks" will come over time; however, you do not want to spin your wheels for 2 weeks trying to figure out something or writing your own when either someone has already done it or someone can point you in the right direction.  In the next couple of weeks/months, Google should become your best friend for Silverlight content!

Innovation

Once Silverlight 2 is out there, it is going to be a large release of Silverlight eye candy.  I think these products will largely replace existing Web 1.0/2.0 features in small chunks.  To me, this reminds me of when the XBOX 360 came out.  The games looked a little better than the XBOX but nothing blew me away.  The next generation of games is where the innovation started.  In my opinion, the same concept applies to Silverlight 2.  Don't think just by adding a carousel, cool intro screen or some animations is it.  Think of what RIA technology inside Silverlight 2 RTM brings to life and how it can REVOLUTIONIZE a business.  The big picture risks always pay the biggest dividends in the long run. The main reason I say this is that Silverlight RIA becomes different than just a "copy" of the Flash/Flex RIA applications.

Microsoft is doing the same.  As I mentioned above, they are going to be releasing additional themes & controls (possibly other back-end libraries).  Silverlight 2 RTM is not going to end with the core library release and the innovation should continue on both sides (Microsoft's and yours).

 

Note: I have made a promise to myself not to rehash other people's ideas and provide original content with my information.  This is why I post infrequently and you will never see posts "Silverlight is out" with a download link.  Having said that, there are a lot of details and information I am omitting from this article.  For further information about Silverlight 2 RC0, check out  Tim Heuer's blog articl on this or Scott Guthrie's blog.

kick it on DotNetKicks.com
Posted: Sep 26 2008, 12:04 by Bart Czernicki | Comments (4) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: Silverlight
Tags:
Social Bookmarks: E-mail | Kick it! | DZone it! | del.icio.us

Silverlight Opportunity: Challenging the game concept model (Spore)

In this article, I am going to go over the latest hot game from EA: Spore.  I plan to discuss how the value provided by the game can largely be replicated by next-gen RIA technologies into profitable business opportunities.

Spore Box

If you are a gamer (like myself), you probably are aware of the release of one of the most anticipated games for the PC.  Before I splurge some money on a game, I like to check it out reviews and see what the game is all about.  Spore for the most part has gotten pretty decent reviews from critics.  There has been some backlash about the DRM, but overall the game is very popular.  For those who do not know, the game essentially allows you to create a creature and watch it evolve from a simple organism to a complex animal.  The game has 5 phases and as your organism evolves, you play different genres of video games (2D action, 3D action, real time strategy).  However, the core feature (as well as the neatest feature) of the game is the ability to share your creature/world in the Sporepedia with other Spore creatures/environments created by other players.  Revolutionay concept, right?

This has been done before several times!  However, most people have a short-term memory.  It is kind of like Puff Daddy releasing a remix or a sample of a song from the 80's and for the current generation. Spore is exactly that; a remix of a concept already done with some glitz.  Not that there is anything wrong with that.  Spore's main difference is that it is packaged with nice graphics with social networking capabilities (sharing your creature, upload videos directly to YouTube).  Guess what?  It is incredibly popular and doing very well so far in sales as well as BitTorrent downloads (which I think in the next few months will actually become a valid gauge for PC distribution, even though it's illegal).

For those who have been playing with .NET since 1.x remember .NET Terrarium (since 2001, now in version 2).  It actually allowed you to learn .NET programming, by using .NET to program your creatures "DNA" and upload them to different environments and see how they interact with other creatures created by other programmers.  As of July 2008, the Terrarium 2.0 code is free and available on CodePlex. Terrarium is geared for programmers, so it actually had much  deeper/more open capabilities.  Spore is geared for the masses, so it has to be simpler and essentially "dumbed down" for the average user.  For example, in Spore if your creature eats a lot of meat, it will become a carnivore and dependent on meat as its food source.  Obviously, terrarium was not released as a game so that example is not 100% fair.

Terrarium

The Spore video game has been released under the traditional model.  Most of the revenue is coming from the sales of the product itself and it includes ridiculous DRM protection (limiting the user to install the game on up to three computers).  As I mentioned above, this concept has been done before.  What value has Spore added to the game?

  • Includes a very cool & easy to use creature creator
  • Allows you to upload your creatures/buildings and share it with other players (as of now, there are over 17 million objects uploaded)
  • Allows you to share videos of your creature and upload them to YouTube

Where the game exposes its weakness is the "campaign/evolution" stages of the game itself.  Each stage is a very basic implementation of some kind of video game genre.  For example, stage 1 is a simple 2D action game where your organism tries to avoid being eaten by bigger animals while looking for food.

Spore Cell Stage

This is where I think Silverlight (and other RIA technologies) can compete in this kind of video game (where the value is NOT in the graphics/immersive experience, etc).  As I mentioned above, Spore adds a lot of value on the server and services side.  The back end is essentially presentation agnostic.  It doesn't matter whether this is an XBOX game or a basic web game.  Furthermore, the social networking aspect of the game is completely abstracted from the gameplay other than translating the results of the gameplay into stored data that is presented on the web or YouTube.  Obviously, if your UI presentation is Silverlight or a fantastic looking DirectX 10 game, the back end services could all be the same.

Let's look at the gameplay and presentation.  Spore's core "action gameplay" is actually pretty simple.  It is nothing that can't be decently reproduced inside Silverlight.  Don't believe me?  For example, one of Spore's more complex 5 stages is the RTS stage.  Even that is a VERY basic RTS (RTS games in the last 10+ years have had more features).  These guys recreated StarCraft (one of the most popular RTS games ever) inside Flash!  If you played Spore, it might not look as pretty; however, the RTS action is actually a lot deeper than Spore's Tribal Stage!  Silverlight already has a particle engine, physics engine, multithreading support, etc., that allow you to create rich gameplay environments easily.  The environments are not going to rival what you can do with DirectX or even the XNA game studio but they can provide a VERY decent gameplay experience. EA asserts that you create a character, you watch it evolve and your decisions affect how it behaves in later stages.  What does that really mean?  A couple of properties transfer over?  We are not talking about a massively complex AI here.  Like I mentioned before, this has been done successfully in Terrarium in .NET 1.0 in 2001!

Spore's busines model achieves a high value through its concept and social networking services.  The loosely tied basic game genres are largely secondary here.  Spore isn't Call of Duty 4 or Crysis, where the value in the game is in the gameplay and ultra high graphics.  This is the exact place I think Silverlight can compete in....Because a lot of Spore's core and value features can be done verbatim inside Silverlight!!!  Since Silverlight is a web technology, this lends itself perfect for a lot of Web 2.0+ revenue channels and reduces distribution further.  Combining RIA technology with web advantages and using their respective advantages properly is the key in finding games that can be ported to RIA technology and will be successful.

If you need further proof, let's look at other gaming environments.  For example, let's look at console games.  The current generation of games for the XBOX 360 release "second tier" games through XBOX Arcade.  You are not going to find games like Madden 2009 for $14.99 there; however, you will find a lot of games that go beyond the graphics and are very successful through novel concepts.  One of the highest rated games on the XBOX 360 is Braid.  It is currently rated #4 out of all XBOX 360 games and an Editor's Choice on Gamespot!  Another recent release, Bionic Commando is another platform game that does some cool stuff with the bionic arm and adds value not normally seen in platformers.  You are not going to re-create Madden or GTA IV inside Silverlight.  However, as you can see from the two examples mentioned, graphics aren't everything.  Providing a great gameplay experience can be as simple as creating a concept that hasn't been created before or can be improved.

In this article I focused on Spore's gameplay architecture; however, this applies to other games where the graphics/presentation are not the primary value in the game.  RIA technologies have a chance to expand beyond simple casual gaming (i.e., www.flashgames247.com) into genres that deliver additional value through integrated services, social networking and deep concepts (i.e., RPG).  With more advertising money pouring into the web and more users spending their entertainment dollar on the web, developing serious, free or cheaper web game alternatives can become lucrative opportunities.  With next-gen RIA technologies becoming richer on all fronts, you WILL see dedicated efforts to bring some successful games from consoles/PCs/handhelds into the RIA.  That is EXACTLY what RIA technology can bring.  It's not about just random "RIA glitz" but using the "RIA glitz" to make the UI better, simpler, easier or more intuative that can rival some professional projects.  Remember, the Spore concept has been done before.  It's packaged better, simpler and prettier.  If you want a piece of the action, you should be asking yourself what concept can I bring into RIA successfully. 

In my next few articles, I will expand on this idea with other detailed examples of games where RIA technology can take a piece of the pie of the web entertainment dollar.

Posted: Sep 14 2008, 07:51 by Bart Czernicki | Comments (4) RSS comment feed |
  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: Silverlight | Video Games
Tags:
Social Bookmarks: E-mail | Kick it! | DZone it! | del.icio.us

Silverlight MultiThreading with a Computational Process (Counting Primes)

Intro 

In my previous post about multithreading I looked at the importance of using multithreaded techniques to improve the performance of the UI controls. This post focuses on using multiple threads to improve computational performance inside Silverlight.

I saw this article by Tim Anderson comparing Silverlight and Flash in a computational situation by counting primes.  I also saw derivatives of this article comparing the performance of Silverlight vs JavaScript/TraceMonkey.  Silverlight is a clear winner in both articles.  However, we can do better.  This article will focus on how we can improve the performance of Tim's code by adding multithreaded processing inside Silverlight.  I am not focusing on math theory, the counting prime algorithm or hacks to make other versions better.  This article focuses on some straightforward Silverlight 2 multithreading optimizations.

kick it on DotNetKicks.com

Demo and Beta 2 Source Code are provided.

Update 10/14/2008..The demo is now on Silverlight 2 RTM and the Silverlight 2 Source Code is up.

Overview of the example & demo:

First, check out Tim Anderson's example and run the example on your machine to see what we are going to be optimizing.  Also, note the performance of the runtime on your workstation.  Run it a couple of times each to get a good baseline. Silverlight should be faster by a factor of 4.

 

 

So let's improve the code with more threads (remember, not the algorithm; I want to keep it the same).  I created a small application that has the standard implementation (standard code); an example with two threads and an example with three threads.  Click on the example below to launch it.

 

  • The first button is essentially Tom's code and performs the code in single thread
  • The second button spins up 2 threads using the BackgroundWorker to calculate the primes (using the same code in the first button)
  • The third button spins up 3 threads using the BackgroundWorker to calculate the primes  (using the same code in the first button)
  • The last input UI control is a textbox that allows you to enter an integer (1 to whatever) to add a factor of 1,000,000 to end with.  For example, 2 will calculate the primes for 2,000,000 integers;  3 will calculate for 3,000,000 integers.  This way we can increase the number of integers we want to calculate by simply changing the integer in the text box  (There is a specific reason why I implemented the prime counter to use this method as I cheat a little bit in the implementation.  More on that below)
Overview of the multithreaded implementation: 

My implementation of how the multiple threads calculate a single process (i.e., counting the primes from 1 -> 1,000,000) is very similar to the logic that is implemented by the Microsoft Parallel Extensions.  Check out the video on Channel 9 where Joe Duffy and Igor Ostrofsky explain how some of the parallel extensions work.  I would recommend watching the entire video; however, you can ffwd to about the 8 minute mark to get a decent understanding of the logic I am mimicking.  Below is a screen shot of the logic that the parallel LINQ uses when dealing with some kind of process on a data structure like an array:

Let's overview the logic that Parallel LINQ uses (It does MUCH more than this, but we are doing something simple at a high level):

  • We have an input array of 5 numbers.
  • In the logic above we are spinning up 2 threads.
    • The first thread will do some kind of processing on the integers: 3, 1, 2
    • The second thread will do some kind of processing on the integers: 5, 6
  • Each thread will store each product in an intermediate data structure
  • After both threads are completed, then the output from the two intermediate structures is combined and returned to the main thread.

This is exactly the same logic I am using for counting primes in a multithreaded environment.

  • We have a number of integers we want to count primes to (i.e., 1,000,000)
  • Say we want to use three threads to calculate primes from 1 -> 1,000,000
    • The first thread will handle the numbers between 1 -> 333,332
    • The second thread will handle the numbers between 333,333 -> 666,666
    • The third thread will handle the numbers between 666,667 -> 1,000,000
  • As each thread finishes, it adds to the count of the integers that are primes.
  • When all three threads finish, the final result is reported back to the main UI thread.
Overview of the key lines of code:

In my previous writeup, I used the BackgroundWorker to implement the processing on multiple threads for this demo.  In this example, I do everything manually and you could write logic to dynamically spin up the necessary threads as needed using delegates.  Like I mentioned, this code mimicks the high level logic in the parallel extensions library.  In the future, I hope that they release a parallel extensions dll for Silverlight which will do exactly what we are simulating in this example/demo.

The code below handles the calculating of primes for three threads:

  private void CalculatePrimesOptimizedThreeThreads_Click(object sender, RoutedEventArgs e)  {  // Reset the variables.  this.threadsReportingThree = 0;  this.multiThreadedPrimesThree = 0;  this.multiThreadedStartThree = DateTime.Now;  /*  You do not want to do this in production code.  I would do something like this once the delegates support async thread invocation.  Func callCalcAsync = this.calculateNumberOfPrimes;  callCalcAsync.BeginInvoke(1, 500000, [add callback method], null);  */  this.bw31.RunWorkerAsync();  this.bw32.RunWorkerAsync();  this.bw33.RunWorkerAsync();  }  

The code in the event handler above simply resets the timespan & count variables. Finally, it spins up the three seperate threads in order to process 1/3rd of the counting of the 1,000,000 primes.

  void bw31_DoWork(object sender, DoWorkEventArgs e)  {  e.Result = this.calculateNumberOfPrimes(1, 333332*this.multiplyFactor);  }  void bw32_DoWork(object sender, DoWorkEventArgs e)  {  e.Result = this.calculateNumberOfPrimes(333332 * this.multiplyFactor + 1, 666666 * this.multiplyFactor);  }  void bw33_DoWork(object sender, DoWorkEventArgs e)  {  e.Result = this.calculateNumberOfPrimes(666666 * this.multiplyFactor + 1, 1000000 * this.multiplyFactor);  }  

The code above shows the processing of each of the three threads do after they are initiated by the RunWorkerAsync() method (in the first code snippet).  Each of the threads calls the calculateNumberOfPrimes method with the respective procesing range passed in.  Simple stuff.

  void bw3_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)  {  // Poor way to do a waithandle. Don't do this in production code.  // Use the waithandle...that's what it's there for.  I am keeping this simple.   // until Silverlight 2 gets full async support  object lockObject = new object();  lock (lockObject)  {  this.threadsReportingThree++;  this.multiThreadedPrimesThree += (int)e.Result;  // Don't do anything until both threads have reported.  if (this.threadsReportingThree == 3)  {  DateTime end = DateTime.Now;  Double timetaken = end.Ticks - this.multiThreadedStartThree.Ticks;  timetaken = timetaken / 10000000;  this.lblCalculatePrimesOptimizedThreeThreads.Text = "Number of primes up to: " + 1000000 * this.multiplyFactor + " is " + this.multiThreadedPrimesThree.ToString() + ", counted in " + timetaken + " secs.";  }  }  }  

In the code above, we are performing the last step of our parallel extensions simulation.  We are synchornizing the result of the three background threads.  As each thread finishes, we add to the number of primes that each thread process has found.  When all three threads finish, we report the result the the UI (main thread).  Note, we do perform a lock on the processing code as we could appear in a race condition with two threads finishing at the same time.  The probability of this is small; however, not thinking about these things usually results in intermittent code and causes weird bugs to occur.  Furthermore,  the more threads to sync, the higher the probability of errors like this occuring.

Performance Gain Tests

Before we start looking at the demo numbers, we need to understand that this processing doesn't come free.  Spinning up extra threads from the threadpool, figuring out which section of work each thread should process, storing the results in intermediate structures and finally synchronizing the threads all have an associated processing cost with them.  Obviously, in production you could adjust the multithreaded logic based on your data/environment(s), make it configurable or make it dynamic and figure out which is the best way to process.  Longer running processes done on client machines with multiple cores will benefit from this multithreaded implementation than those that don't meet this criteria.

Performance Gain Tests - Test Core 2 Due 2.2 GigHz

The first test machine is a Core 2 Duo 2.2 GigHz.  The workstation has two physical cores, so it can handle multiple processes better than a single core processor.  Depending on your workstation specs, you may receive different results.  This is a typical standard desktop/laptop you could buy from Dell/HP in the last 1.5-2 years. 

Test 1 (counting the number of primes from 1 -> 1,000,000).  Factor is the default: 1

  • Single thread time: .362 seconds
  • Two threads time:  .256 seconds
  • Three threads time: .257 seconds

Notice right off that multithreading the computation already netted a nice performance gain of over 40%!  Notice there isn't much of a difference between two threads and three threads.  Remember, when I mentioned above that there is a cost associated with each thread you use in splitting up processing on each core.  Obviously, the cost here is roughly equal to the benefit.  Therefore, they wash each other out and three threads process in about the same total time as two threads.  One way to mitigate the cost of multiple threads on a core is to increase the amount of available cores :)

Test 2 (counting the number of primes from 1 -> 5,000,000).  Factor is the default: 5 (dramatically increases the processing time).  I ran these tests multiple times and picked the lowest run I received (You will receive different results as you may have different items running in the background on your workstation).

  • Single thread time: 3.194 seconds
  • Two threads time:  2.031 seconds
  • Three threads time: 1.719 seconds

In this example, we can see that the difference between the single threaded and dual threaded implementation is about 1.1 seconds!  That is a huge difference.  Let's look at the three thread implementation.  It actually came in 0.3 seconds lower than the two thread implementation.  So now we are seeing some benefits of our third implementation.  It is not very drastic; however, as we increase the processing needed, the difference gap will increase further in the time span.  The percentage different should remain roughly the same.

Performance Gain Tests - Dual Processor Quad-Core HaperTown 5420 (Intel Xeon 2.5 GigHz)

The second test machine is a server: Quad-Core 2.5 GigHz.  The server has 8 physical cores.  This test is just to show what results we come up with when the cores are increased by 4x. 

Test 1 (counting the number of primes from 1 -> 1,000,000).  Factor is the default: 1

  • Single thread time: .234 seconds
  • Two threads time:  .15625 seconds
  • Three threads time: .1093 seconds

With a higher class of processor, these times are a lot faster than the previous results.  However, with 2 extra cores now our three thread implementation is already 42% faster than the two thread implementation.  Note that during our test on a dual core, the three thread implementaton was indentical to the two thread implementation.

Test 2 (counting the number of primes from 1 -> 5,000,000).  Factor is the default: 5 (dramatically increases the processing time).  I ran these tests multiple times and picked the lowest run I received (You will receive different results as you may have different items running in the background on your workstation).

  • Single thread time: 2.25 seconds
  • Two threads time:  1.401 seconds
  • Three threads time: 0.997 seconds

The times are obviously faster and the margins are about equal between the last test (The three thread implementation is about 40%+ faster than two thread implementation). The performance of the three threads is 125% faster than a single threaded computation!

What's happening during the tests?

If you have a dual-core or a quad-core workstation, you can try this yourself by simply opening up task manager (while testing different implementations).  I set the factor to 15 to count the number of primes from 1 -> 15,000,000.  This will simulate a longer running process that hopefully registers properly on the task manager.

Above is a screen shot of the task manager CPU usage of both cores while performing the prime calculation for 15,000,000 integers.  The data in the red box was captured for the single threaded implementation.  The data in the blue box was captured for the multithreaded implementation (2 threads).  Notice from the graph that the duration for the single threaded implementation is longer than the multithreaded implementation.  Furthermore, during that duration the single threaded implementation does not take full advantage of both cores.  The CPU does some switching automatically for the process; however, it's not perfect.  Contrast this with the multithreaded implementation which spikes both cores to 100% and keeps it at 100% until the processing has finished.  The graph in the blue is the kind of graph you want to see from a fully multithreaded process.

Who cares?  Why would I want to do this in a web app?

In the world of Web 1.0 and maybe even Web 2.0 days, you probably would want to leave heavy processing to a server or move to a fat client application.  With the start of cloud computing, Web 3.0 or "Web OSes" more is expected from web sites inside the browser.  Multithreading isn't just about AJAX and calling a web service anymore.  Inside Silverlight, you can do some real powerful optimizations by leveraging multiple threads.  This can be useful in a lot of areas.  Just to name a few:

  • Silverlight game programming (i.e., AI)
  • Applications that handle a lot of data
  • Simple math/physics simulations
  • Server monitoring of processes, databases, etc.

If you are professional programmer reading this, I hope I don't have to convince you to utilize multithreaded patterns in your code to net 40% performance gains! :) Just take a look at the net gain on a server machine with three threads...125%!  This is with my simple/manual/hacky waithandle logic, so there is definitely more improvement to be netted here.

My last two articles gave detailed examples of multithreading, which were an intro to my next post in my Silverlight Master Series. 

Beta 2 Source code: SilverlightPrimes.zip (544.08 kb)

Silverlight 2 RTM code: SilverlightPrimes_RTM.zip (543.73 kb)

Posted: Sep 07 2008, 13:23 by Bart Czernicki | Comments (4) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Social Bookmarks: E-mail | Kick it! | DZone it! | del.icio.us

Sliverlight Multithreading with Controls (Slider example)

In the next couple of entries in my Silverlight Series, I am going to talk about multithreading, LINQ, etc., and how they can be used inside Silverlight to create rich applications.  However, I thought it might be a good idea to give a simple and well-explained example of before delving too much into why multithreading in Silverlight is important (vice versa). In this article, I want to briefly introduce multithreading inside Silverlight and the show how one can improve UI performance by introducing secondary threads into the events from UI controls.

Demo and Source Code are provided.

Update 10/14/2008..The demo is now on Silverlight 2 RTM and the Silverlight 2 Source Code is up.

Introduction

Silverlight runs as a plug-in inside the browser.  Some people describe it as "Flash" or a virtual desktop.  The virtual desktop is a good analogy to desktop (fat client) programming.  Those familiar with writing desktop applications know if you have long-running method calls (i.e., scanning the hard drive), making a database call or a web service call, that is done on the main UI thread by default.  Experienced developers know that making these calls on the main thread can cause the UI to become unresponsive or completely give the appearance of a blank UI window.  Creating a responsive UI usually entailed the desktop developer delving into mulithreading the background calls and keeping the main thread primarily to be used for UI operations.  Silverlight UI development shares these UI characteristics of desktop development.

The Silverlight team at Microsoft wants Silverlight to shine and perform "out of the box" by making the multithreaded choice for you. 

  • If you have done any kind of Silverlight service call, you already have a mental note that Silverlight already does a lot work for you on secondary threads.  Calling a WCF service or an ADO.NET Data Service is done on a secondary thread with all the events properly dispatching to the main thread.  This is a plus that developers not too familiar with .NET & multithreading can create responsive (in terms of UI) applications because they have no other choice :)
  • Silverlight takes this further and certain objects like the StoryBoard or Timers are also done on seperate threads.  This allows the developer/designer to create animations without having to worry about multithreading for performance as it is done for you. 
  • When you first hit a website that has Silverlight content, it will be brought down while a progress inidicator (whether it is the default or a custom implementation) shows how far along a user is in downloading content.  While the last example is not a true example of multithreading inside Silverlight, it does amplify the fact that Silverlight has a lot of multithreaded content "out of the box" and nudges the UI developer towards that way.

Not everything inside Silverlight multthreading is "out of the box" and a professional Silverlight developer has to understand that adding expensive calls based on UI controlled events will cause the Silverlight application to beome unresponsive.  Luckily Silverlight 2 includes a rich subset of the .NET 3.5 (SP1) stack and there are many options for developers dealing with multithreaded design.

Example & Demo with the Slider control

The Slider is a real basic control inside Silverlight.  You have seen the Slider implementated anywhere as a volume control or even as a query tool (i.e., Amazon diamond search).  A slider is designed to have a smooth user experience.  The user should be able to quickly move the slider thumb into position and clearly know what value they are on.

What if the movement of the slider thumb is associated with an expensive calculation, web service call or long LINQ query?  The demonstration below shows us three different sliders:

  • The first slider is a simple slider that performs a very quick output to the UI with how many times the move event was fired and the current value of the slider thumb.
    • Notice how many events are fired for just a simple "slide movement".
    • Just a simple movement from beginning to end can cause event handler to be called 30+ times (This depends on how slow you move the slider).
  • The second slider simulates a heavy operation.  It includes a 150ms operation inside the event handler method.
    • Notice the "sliding" movement operation is now seriously degraded.
    • The granularity of the slider is also impaired.  Because of the delay, it is harder to move the slider to the exact position we want.
    • Fast slider movement causes "big jumps" in the slider.
  • The third slider includes the EXACT same 150ms delay simulation.  The big difference is that the "heavy work" is done on a seperate thread and not on the main thread.
    • Notice the performance compared to the second slider.
    • The granularity and thumb movement is a lot better.  The user would not even notice that there is a significant process being done behind the scenes.
Code Overview

The source code is commented and self-explanatory for the most part. I do want to go over the multithreaded implementation in Silverlight.  Silverlight 2 Beta 2 currently does not support asynchronous delegates.  There are a few ways to write multithreaded processes.  The best way in Beta is probably utilizing the BackgroundWorker class.  Those familiar with desktop programming will be familiar with the implementation.  The BackgroundWorker automatically controls the secondary thread and properly threads dispatching through events/delegates.  It makes adding expensive processes on secondary threads trivial.

Let's go over some key parts of the code:

We declare the BackgroundWorker as a field, so it is properly scoped and can be used throughout the code file.  Furthermore, we want to wire up two events to their methods.  RunWorkerCompleted event fires after the work on the secondary thread has completed.  We can use this to get a result from the work or simply notify the UI that the process has finished.  The DoWork is the actual process that will be executed on the secondary thread.  This method will simulate the heavy work.

// declare background workerBackgroundWorker bw = new BackgroundWorker();public Page(){InitializeComponent();// wire up background worker eventsthis.bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);this.bw.DoWork += new DoWorkEventHandler(bw_DoWork);}

Now that we have the our BackGroundWorker defined and wired up to fire methods, we need to declare these two methods: 

  • The bw_DoWork method is pretty simple and just puts the current thread to sleep for 150 milliseconds.  Note that when you are in this thread, you are executing on the background thread not the main thread.  So this will put the secondary thread to sleep, not the main UI thread.  Furthermore, you cannot access any UI objects.  This will throw a cross-reference exception.
  • The bw_RunWorkerCompleted method is called after the 150 millisecond delay is complete.  This method is called on the main UI thread so it is safe to access UI objects.  What happens in this method is simple; Since I am done processing whatever my slider move caused, I simply notify the UI what the current value is.
    • Note the code calls itself again if the user moved the slider while the code was in the middle of processing on the second thread.
void bw_DoWork(object sender, DoWorkEventArgs e){// add a fake delay of 150 milliseconds (3/20 of a second)System.Threading.Thread.Sleep(150);}void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e){// Set the slider value to its text box// Notice this is set here, as it guarantees that the value is now officially set// Setting it in the SliderMultiThreaded_ValueChanged event, the 2nd thread would have to catch up to the UIthis.txtSliderMultiThreadedValue.Text = this.SliderMultiThreaded.Value.ToString();// Run the background worker again in case the Slider value needs to catch up// If you stop the slider at the end, for example, it might be still processing the previous event// You want to make sure that where the slider is stopped (last event fired) matches what was processed by the 2nd threadif (!this.bw.IsBusy){// If the values are not in sync, then the 2nd thread needs to catch up to the UIif ((this.SliderMultiThreaded.Value != this.LastMultiThreadedSliderValue) && (this.LastMultiThreadedSliderValue != 0.0)){// Run the process again, if the last value set has not been run by the second threadthis.bw.RunWorkerAsync();// set the value to 0.0this.LastMultiThreadedSliderValue = 0.0;}}}

Kicking off the asynchronous process is simply done by calling the RunAsync() method on the BackgroundWorker variable (bw in our example) in the SliderMultiThreaded_ValueChanged event. This method is non-blocking on the UI thread and if you debug it, it will look like it finishes instantly. It actually spins up a secondary thread and performs the logic inside the bw_DoWork() method we defined above.  Notice below that the code only fires the asynchronous process if the BackGroundWorker is not busy.  This is key, as this will throw an exception if we try to kick off another process on the BackGroundWorker if it is not done.  This is why we have to do the "catch up" step above because the secondary thread could be busy processing the work while the user triggers another slider change event by moving the slider thumb.

private void SliderMultiThreaded_ValueChanged(object sender, RoutedPropertyChangedEventArgs e){// increment multi threaded slider event countthis.countSliderMultiThreaded++;// Set the last value set compared to the current valuethis.LastMultiThreadedSliderValue = this.SliderMultiThreaded.Value;// Execute the work on a second threadif (!bw.IsBusy){bw.RunWorkerAsync();}// Set the count on the text boxthis.txtSliderMultiThreadNumberEventFires.Text = this.countSliderMultiThreaded.ToString();}
Compare to other RIA  Technologies (Flex, Java)

How does this compare to Flash/Flex?  As of now even with Silverlight's limited multithreading support (Dispatcher, StoryBoards, BackgroundWorker, Services/Sockets, etc.), it actually is a lot better than Flash/Flex.  Flash/Flex DO NOT have multithreading support (at least as I understand it).  There is some multithreading in Flash 10 (which is also in beta).  I do not use Flash/Flex, from what I understand the new multithreading capabilites are more behind the scenes and do not include a first class multithreading and thread synchronization environment.  I was pretty suprised when I found that out and I see that is a huge problem for Flash/Flex. 

Many people who disagreed with me in my previous post when I listed the advantages of Silverlight over Flash at least agreed .NET favored Silverlight.  .NET is too much of a broad statement to simply state a simple advantage because of the MANY subpoints that .NET brings to Silverlight.  Simply saying .NET as an advantage is a big understatement. First class multithreading support is a huge win for Silverlight vs Flex/Flash.  Why does this matter?  Because any computer made in the last couple of years probably has a dual processor or more inside it.  It is all about adding cores not adding processing speed.  Silverlight takes advantage of this and it's only in beta!  You could write a similar slider application inside Flash/Flex with some tricks (using a resource govenor to manage the thread like context switching), but why would you want to??!!  Silverlight is already way ahead in the multithreading game compared to Adobe's RIA product.

JavaFX does have multithreading support for certain keywords used as triggers.  I wouldn't call it the same thing that Silverlight 2 RTM will offer.  However, JavaFX and Java can be used together and Java does offer full multithreading support.  Silverlight is nice in that it offers first class support all in one spot in one language.

Conclusion & Future

With this demo, I tried to drive home the point that in order to create the best UI experience for Silverlight users, ensure that you leverage all of the features inside the .NET Framework.  In my opinion, this is what makes Silverlight shine compared to other RIA technologies.  Silverlight 2.0 Beta 2 includes several options to add multithreading capabilities to your RIA applications.  Once delegates are added and are able to invoke methods asynchronously, this logic can become a lot more clearer and lot more functional looking (.NET 3.5 -> lambda expressions, etc.). 

In the RTM release I see Silverlight supporting full delegates with dynamic invoking and my hope is that PLINQ/Parallel Library will come to Silverlight as well.  If those two things happen, Silverlight will be the clear leader for multithreaded RIAs and allow you to write very performant applications.

kick it on DotNetKicks.com

Silverlight 2 Beta 2 Code: Silverlighthack_SlidersMultiThreadedExample.zip (545.41 kb)

Silverlight 2 RTM Code: Silverlighthack_SlidersMultiThreadedExample_RTM.zip (547.45 kb)

Posted: Sep 01 2008, 12:06 by Bart Czernicki | Comments (11) RSS comment feed |
  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Social Bookmarks: E-mail | Kick it! | DZone it! | del.icio.us