In web-based server applications, performance optimization is understandably a very necessary part of the software development lifecycle—after all, you are writing code to service hundreds of users at the same time. However, in a single user environment, such as the mobile device, you might wonder if this is necessary.
The truth is, sometimes mobile users may not need applications that run faster, but applications that respond faster. A mobile device has hardware limitations that will always place it behind the PC in terms of power and speed, so it will never be expected to number crunch or load data as fast as the PC can. By designing your mobile application so that it will be constantly and highly responsive to user input, it can make up for its limitations by providing a more fluid user experience.
In this chapter, you will learn how to write faster .NET CF code that facilitates responsive user interfaces. You will cover the following:
Before you can optimize your code for performance, you obviously need to know if it is underperforming in the first place. You can measure performance at two basic levels—at the code level and at the application level.
At the code level, developers typically use timers in order to time sections of code and to then display the time taken for the piece of code to execute. At the application level, the developer might need to know, for instance, how much memory an application has been consuming or how many times garbage was collected during its lifetime.
In the following sections, we will explore how you can set up your code and application to collect this diagnostic information.
The most basic way to measure the performance of a piece of code is to:
There are a few ways to capture time. First, you have the Environment.TickCount
.NET method (which is based on the Win32 API GetTickCount()
method). It returns the amount of time (in milliseconds) that has passed since the device booted. However, there are two immediate problems with Environment.TickCount:
The better (and more accurate) way to measure time would be to use a high resolution timer. The QueryPerformanceCounter
method returns the current value of the high resolution performance counter, and the QueryPerformanceFrequency
method the number of counts per second. To measure performance, you can:
QueryPerformanceCounter
to capture the start time. QueryPerformanceCounter
again to capture the end time. QueryPerformanceFrequency
. This will return the amount of seconds elapsed. You can also retrieve the time in milliseconds by performing a simple conversion.Let's build a class to do this. Create a new class called PerfTimer
and add it to the CRMLiveFramework
project. You will need two functions: Start
and Stop
, to signal the capturing of the start time and corresponding stop time. The Stop
function will return the amount of time elapsed (in milliseconds).
The QueryPerformanceCounter
and QueryPerformanceFrequency
functions are Win32 API functions and do not have any .NET framework equivalent. You will thus need to declare these external functions using the DllImport
keyword. The code for the PerfTimer
class follows:
using System;
using System.Runtime.InteropServices;
public class PerfTimer
{
[DllImport("coredll.dll", EntryPoint =
"QueryPerformanceCounter")]public static extern int
QueryPerformanceCounter(long perfCounter);
[DllImport("coredll.dll", EntryPoint =
"QueryPerformanceFrequency")]public static extern int
QueryPerformanceFrequency(long frequency);
private long _timerFreq;
private long _startTime;
private long _endTime;
public PerfTimer()
{
if (QueryPerformanceFrequency(_timerFreq) == 0)
{
throw (new Exception("Could not retrieve timer
frequency"));
}
}
public void StartTimer()
{
if (QueryPerformanceCounter(_startTime) == 0)
{
throw (new Exception("Could not retrieve timer start time"));
}
}
public long StopTimer()
{
if (QueryPerformanceCounter(_endTime) == 0)
{
throw (new Exception("Could not retrieve timer end time"));
}
return ((_endTime - _startTime) * 1000) / _timerFreq;
}
}
Now let's see how you can use this class. In the SalesForceApp
project, open the AccountDetails
form. Look for the RefreshPage
method. The GetAccountsByType
method is called here—let's measure the time it takes for the dataset to be retrieved from this method call. Add the lines highlighted in the following code:
private void RefreshPage()
{
try
{
PerfTimer _timer = new PerfTimer();
_timer.StartTimer();
_accounts =
GlobalArea.Application.GetAccountsByType(_type,
_totalRecords, pgPager.CurrentPage, _recordsPerPage,
_SortColumn, _SortOrder);
MessageBox.Show("Data retrieved in :" +
_timer.StopTimer() + " milliseconds");
dgAccounts.DataSource = _accounts;
dgAccounts.Refresh();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
Run the application and try opening the Leads Listing page. The message shown in the next screenshot will be immediately displayed.
In the preceding section, you've learned how to measure performance at the code level. However, you can also retrieve performance statistics at the application's working-set level via internal counters maintained by the .NET Compact Framework. This includes, for example, the amount of memory allocated or deallocated during the application's execution.
To activate these performance counters, you will first need to enable a key in the registry of your mobile device. Windows Mobile does not come with a tool to edit the registry, so you will either need to get a third-party tool or do it remotely from your desktop using the bundled CE Remote Tools package from Microsoft.
Launch the ccregedt.exe
application from this location on your desktop:
Program FilesCE Remote Tools5.01inccregedt.exe
You should be able to see a window that allows you to choose a target device. Choose the Windows Mobile 6 Professional Emulator device.
This will launch the emulator. At the same time, you will be able to edit the registry details for the emulator device using an interface that is similar to the desktop-based regedit.exe
tool.
Expand the Windows Mobile 6 Professional Emulator node and create a new key named PerfMonitor
under the following key:
HKEY_LOCAL_MACHINESoftwareMicrosoft.NET CompactFramework
In this key, create a DWORD
value with the name Counters
, and set its value to 1
. This will signal the framework to generate a .Stat
file whenever a managed application executes. If you wish to disable capturing of performance statistics, set this value to 0
. This key and value can be seen in the following screenshot:
You can save the emulator's state at this point. Run the sales force application now by navigating to its folder. After the application launches, close and exit the application. You will now notice that a new file with the name of your application and the .stat
extension (for example, SalesForceApp.stat
) has been automatically generated in the root folder of the device.
Copy this file to your desktop and open it using Microsoft Excel. You will be able to see a list of performance counters and their values. Through this set of statistics, you can determine the total amount of different resources used throughout your application. If, for instance, you wanted to reduce the memory footprint size of your application, you could use this set of statistics as a gauge for memory consumption.
You can also view the .stat
file using the .NET Compact Framework Remote Performance Monitor tool at the following location:
Program FilesMicrosoft.NETSDKCompactFrameworkv2.0inNetCFRPM.exe
You can open a .stat
file from the File | Open menu in the tool. The Remote Performance Monitor displays a more comprehensive view of the counters together with brief explanations of each counter.
You can read about each of these counters listed in the previous section in detail at the following location:
3.137.160.137