Best Practices of Compact Framework
This shares a few recommendations for use in our day to day development of Compact Framework applications.
Developing applications for mobile devices, such as Pocket PCs and mobile phones, is very interesting, I feel excited when I develop Compact Framework applications. Mobile devices are memory-constrained devices. It is very important for every developer to pay attention to efficient memory utilization and application performance. Recently I got a few mails from developers to asking how to leverage the performance of mobile device applications. In this article I am sharing a few recommendations for use in our day to day development of Compact Framework applications.
We are extensively using base class library collection classes to store a group of objects, if we store any value type in a collection class then (let's say storing an int into an ArrayList) that causes the overhead of boxing and unboxing. To avoid this it is better to define a custom class and make the value type as a member variable and store the class instance in an ArrayList. We can get the advantage of generics in the Compact Framework 2.0 to avoid boxing/unboxing and up-casting/down-casting of collection objects.
Another important pointer regarding collection classes is to pre-size the collection before inserting objects into it. It is recommend to define the size of the collection class rather than depending upon the default size (the default capacity of an ArrayList is 4). Once your collection grows beyond the default capacity, it is resized frequently depending on the type of object storage and the auto expansion of the collection is an overhead process, the recommended solution is to pre-size the collection class before use. Similarly use "for" instead of "foreach" because foreach involves a sequence of virtual methods (GetEnumerator(), get_Current(), and MoveNext()) calls through the IEnumerator interface.
A Virtual method call is performance overhead for your application because virtual methods are never inlined by JIT when a virtual method is called, the Compact Framework walks the class and interfaces hierarchy looking for a requested method by name and call signature, other performance overhead is it is approximately two times slower then static and instance method calls. If you need a virtual call the best thing is to implement functionality as much as you can in a single virtual method rather than splitting into multiple methods and do not make most frequently called methods as virtual. Similarly PInvoke and COM method calls are 6 times slower than managed instance method calls, a native method call is faster than an instance method call. It is recommended to design your class based on the preceding statistics to leverage performance.
If you are using a structure and calling a ToString() or Equal() method, it is better to override these methods, otherwise it leads to boxing and un-boxing issues.
Direct field access is faster than having a property call because the property is nothing but getter and setter methods. The simple properties are inlined by JIT but this assumption may not work always if it involves a virtual setter/getter method call or any complex operation. In order to inline a method your application must have the IL code less then 16 bytes, no branching ( typically "if"), no local variables, no exception handler and so on. It is not possible to predict with 100% accuracy whether a method will be inlined or not, method inlining never occurrs if your application is running in debug mode. So if we can keep performance critical methods as simple as possible then there might be a chance for method inlining.
We frequently use DateTime in our application development. To leverage the performance of DateTime, store it in binary format using ticks but local times are an exception to this recommendation, for DateTime serialization if you know the exact format it is better to specify parsing. Take the advantage of DateTime.ParseExact() to avoid DateTime parser to apply a sequential culture-specific format to date and time string. The same rule is applicable to numeric parsing also.
For GUI performance, try to reduce the number of method calls during initialization and for certain controls you need to do manual modification of design-generated code to leverage performance. Always try to use BeginUpdate() and EndUpdate() for ListView and Tree View. Use SuspendLayout/ResumeLayout while repositioning controls. For GUI performance I recommend to refer to:
Consuming web services is overhead for Compact Framework applications because the Compact Framework uses a reflection mechanism to examine the service's proxy and it never caches this result that usually the full Compact Framework does. It is strongly recommended to not to have multiple instances of the same web service to increase the performance of a web service. Try to maintain a single global instance of the web service, avoid sending datasets over a Web Service, because it pulls in a large amount of XML and uses a complex algorithm for loading data. If you are sending/receiving a DataSet then ensure the schema is serialized alternatively or manually serialize dataset as an XML string before making a web service call.
For Compact Framework performance related information please refer to: