One of the most common questions we are asked is how fast is .NET Compact Framework?

There are 2 things that will help you the most for your project:
1. Learning how .NET Compact Framework is architected from a performance viewpoint, you'd get do's and don't while coding up a managed application.

A lot has been already described about this and I don't have anything to add that's not already in these awesome blogs from Mike, Scott and Roman:
http://blogs.msdn.com/mikezintel/archive/2005/03/30/403941.aspx
http://blogs.msdn.com/scottholden/archive/2005/01/05/346770.aspx
http://blogs.msdn.com/netcfteam/archive/2005/05/04/414820.aspx

2. Measuring your key scenarios using kernels early in the project.

Before writing a huge and bulky project in .NET Compact Framework, you should measure the running times using small kernel programs that are representative of your scenarios. It's said that the 3 important keywords to writing a performant application are "Measure, measure, measure...". Make sure that you have performance goals in mind at the very beginning of the project. Sometimes performance can be tweaked as an after thought, but in most cases this might require huge architectural changes and major rewrites of parts of your program. A few pointers when doing this performance measurement:

 1. Put the operation you want to measure the time of in a loop. Measure the time before starting the loop and after the end of the loop. Do NOT measure the time for each iteration of the loop. Make sure that the loop has enough iterations to run for a few seconds. Run the test many times and average the times. The reason for there is some measurement error and if you time within each iteration of the loop, you are increasing the error. A simple example of seeing how long it takes to read from an XML File is:

 startTime = Enviroment.TickCount();
 for(int i=0;i<5000000;i++)
 {
  // Code to read from XML File
 }
 endTime = Enviroment.TickCount();

 TimePerIteration = (endTime-startTime) / 5000000;

 2. A second baseline for comparison, might be to translate the same kernel above to native code and see how long it takes for the same loop to execute. This way you can measure the overhead of managed code compared to native code. In some cases, the managed implementation could be faster than the native implementation due to the performance tweaks that we have done in the Compact Framework.

 3. If on the whole, the .NET Compact Framework program meets your performance goals except for a few scenarios (and the native implementation meets your goals), you could look at PInvoking to native code for those specific scenarios. However, we recommend against this as we have a robust framework and there might be some error checking that you might fail to do in your native kernel that gives it better performance. The PInvoke route is an option to not writing the entire application in native code, but just a few key pieces. (Think of it as what we used to do when comparing assembly code kernels in a mostly C program a sometime back...). Also, another option for scenarios that don't meet your performance goals, is to rewrite managed code using a different mechanism. There are multiple ways to perform the same functionality - like for instance, you can program to sockets rather than to web services. Of course, there are ease of use, interop considerations to take into account, but these tradeoffs need to be made early in the cycle rather than later.

 4. Sometimes there are variations in the time of the measured benchmark kernel. Turning on performance counters (http://msdn2.microsoft.com/en-us/library/ms172525) you can see if there are things that affect execution time by randomizing it. Things you should look for are GC's, JIT code pitches etc. If you loop is creating a huge amount of garbage, this might not be avoidable (But then if that's your scenario, you would like GC to execute cause then it's typical). If not, and the GC just happened to occur while you were executing the function - then you could add a GC.Collect() before starting the measurement of your kernel to eliminate the effects of GC on your timing.

 5. In order to get managed code to execute, there are 2 stages: JIT stage and running the Jitted code stage. In typical long running programs, the 2nd stage is the one that's important and takes the longest time. As a result, one of the common things we do when we measure performance it we prime the JITing process. That is we execute the operation once before we start measuring the time in a loop. This JIT's all the code in the codepath that's being measured before you actually start measuring the time and hence you get a more accurate timing of the 2nd stage which represents execution of the program.


 For example:

 Foo.Test();

 startTime = Enviroment.TickCount();
 for(int i=0;i<5000000;i++)
 {
  Foo.Test();
 }
 endTime = Enviroment.TickCount();

 TimePerIteration = (endTime-startTime) / 5000000;


This posting is provided "AS IS" with no warranties, and confers no rights.