How to: Improve Performance
The following programming practices can save memory and improve the performance for device applications.
To save memory with Windows Forms and graphics
Use the BeginUpdate and EndUpdate methods on controls that offer them, such as ComboBox, ListBox, ListView, ToolStripComboBox, and TreeView.
Use the SuspendLayout and ResumeLayout methods when repositioning controls.
Load other forms in the background and populate controls with data before using the Show method.
Limit event handling code to perform only essential tasks, so that pending processes can continue.
Use an off-screen bitmap. For an example, see How to: Draw Images Off-Screen.
Override the OnKeyDown, OnKeyPress, and OnKeyUp methods on controls instead of adding key event handlers.
To save memory with data and strings
Use integer variables (Int32 or Int64) in for loops instead of object variables.
Avoid using the ToString method of an enumeration because of the performance impact it incurs by searching metadata tables.
Avoid OutOfMemoryException errors. This exception can be thrown by the common language runtime when there is not enough memory to allocate for internal purposes or new object instances. To avoid this exception, avoid programming large methods that consume 64 or more kilobytes of memory.
Remove System.SR.dll, which contains error message strings for exception dialog boxes. You can deploy your application without this file to save memory. The .NET Compact Framework dynamically loads error strings contained in System.SR.dll if the file is present.
If this .dll file is not present on the device, all exceptions contain the message "Cannot load resource assembly." During development, however, it is useful to add a reference to System.SR.dll to your Microsoft Visual Studio 2005 project so you will see meaningful exceptions.
Strings are immutable, so a new String object is created every time you modify the string. Consider using a StringBuilder when constructing a string that will be modified often.
Use the ParseExact method for a DateTime if you know the exact format used for DateTime serialization. Otherwise, the DateTime parser will sequentially try to apply several culture-specific formats.
Limit the number of open SqlCeCommand objects and dispose of them when finished.
To save memory when interoperating with native code
In platform invoke operations, use blittable types, which have a common representation in both managed and unmanaged memory, such as Int32 or IntPtr. Blittable value types larger than 32 bits are more quickly passed by reference than by value. For more information about blittable types, see .NET Compact Framework Blittable Types.
Use the InAttribute and OutAttribute attributes for the arguments in your function signature to reduce unnecessary marshaling.
Use the methods in the Marshal class to manually convert between IntPtr and managed objects, such as PtrToStructure, PtrToStringBSTR, GetObjectForNativeVariant, and GetObjectForIUnknown.
Use the Prelink and PrelinkAll methods to cause JIT-compilation of the stub that supports native to managed calls.
If you expect your native COM object to return S_FALSE as a common case, or other non S_OK HRESULT values, set the PreserveSig field to true and make the managed signature match the native signature. This avoids the overhead of a try/catch block necessary when the runtime translates HRESULT values
Do as much work as you can in one platform invoke call rather than using multiple calls.
To save memory in collections
Use indexers if the collection is based on an array.
Whenever possible, specify the size of your collection, because dynamic resizing can greatly increase excess storage.
Use generic collections to avoid the boxing and unboxing overhead for value types. Defining your own optimized collection results in the best performance.
To save memory in XML
Use XmlTextReader and XmlTextWriter instead of XmlDocument, which uses more memory.
Specify settings for XmlReaderSettings and XmlWriterSettings to improve performance. The IgnoreWhitespace and IgnoreComments property values, if applicable, can improve performance significantly.
Use UTF-8, ASCII, and UTF-16 character encodings, which are faster than ANSI and Windows codepage encodings.
Avoid using a schema for parsing, because it requires additional validation work.
Map columns as attributes and use a typed DataSet when populating a DataSet from form an XML source.
Avoid the following when populating a DataSet:
Schema inference.
Nested tables.
Several DateTime columns. For better performance, use the Ticks property value instead.
The following guidelines improve performance when using XML deserialization:
Keep element and attribute names as short as possible because every character must be validated.
XML based on attribute data is faster than XML based on element data.
Use the System.Xml.XmlNodeReader.Skip method when applicable.
Consider binary serialization when performance becomes critical.
Use one XmlSerializer instance per type for XML serialization to reduce the amount of time spent searching for metadata.
Because serializing large amounts of XML can use up memory, consider building a custom binary serialization mechanism instead, using a BinaryReader and BinaryWriter.
To save memory when using a Web service
Use a DiffGram when reading and writing a DataSet. For more information, see DiffGrams.
Save a remote DataSet and its schema to the device as XML.
Make a simple Web service method call during your splash screen because the first call is slower than subsequent calls.
Be careful to handle network and data errors.
In some cases, manually serializing the DataSet as an XML string before making a Web service call results in better performance.
To save memory in advanced programming
Process large operations asynchronously.
Avoid virtual calls. The .NET Compact Framework runtime virtual calls are approximately 30 percent slower than static or instance calls. The .NET Compact Framework does not use vtables because of constrained resources, so methods must be called by traversing the class and interface hierarchy, which is an expensive operation. The .NET Compact Framework maintains a cache of resolved virtual calls, so in most cases calls do not need to be reinterpreted.
Use fields instead of properties where possible.
Override the GetHashCode and Equals methods when defining a value type. If they are not overridden, the runtime uses generalized versions for these methods in the base ValueType class.
Use caution with reflection. Using reflection for investigative purposes with un-instantiated classes can impact the performance of the instantiated objects in your application.
Ensure that your managed resources have fully qualified type names and are accurate in your RESX file. They must have the correct version and the PublicKeyToken fields. The effort to find the most appropriate substitute for an improperly specified type impacts performance.
Note that in some cases reading application data directly from the file may be sufficient and more efficient than using ResourceManager. A ResourceManager may probe multiple locations in the file system to find a best matching satellite assembly before it locates your resource binary. Use appropriate tools for the job.
See Also
Concepts
Device Memory Management
.NET Compact Framework How-To Topics