Title: Developing performing mobile applications with the .NET Compact Framework
1Developing performing mobile applications with
the .NET Compact Framework
- Malek Kemmou
- CEO Arrabeta
- kemmou_at_kemmou.com
2xmlContainer.Render()
-
-
- CEO Arrabeta (consulting firm based in
Casablanca Morocco)
- Newtelligence Alliance Partner
- Senior Consultant and Senior Trainer
- Solutions Architecture, integration,
interoperability - Microsoft Regional Director for Middle East
and Africa - Ineta MEA Speaker Bureau
- Speaker at many conferences and events
(TechEd, NDC, MDC, DevDays, DevEssentials ) -
3Microsoft Regional Directors
- http//www.microsoft.com/rd
- 140 experts from all around the world
- Speaking at PDC 2004
- Clemens Vasters (Germany)
- Stephen Forte (New York)
- Farhan Mohammad (Minesota)
- Goksin Bakir (Turkey)
- Malek Kemmou (Morocco)
- Ahmad Badr (Egypt)
- Hossam Khalifa (Egypt)
4Agenda
- Performance and the mobile world
- General Principles
- .Net Compact Framework Specifics
- Common Language Runtime
- Base Class Librairies
- Best Practices
5Performanceand the Mobile World
- Windows Mobile 2003
- Faster, more performing, but still
- Performance outweighs many other considerations
- Architecture
- Maintenance
- Readability
- Real vs. perceived performance
- Hunting down every latency
- Avoiding memory saturation
6General PrinciplesGolden Rules of Performance
- Make performance a functional requirement
- Set performance goals as early as possible
- Revise performance goals at each milestone
- Design, code and test for performance throughout
application life-cycle
7General PrinciplesIn general
- Less code is faster code
- Fewer objects are better for performance
- Recycle and re-use expensive resources
- Batch work where possible
- Initialize lazily
- Do work in the background to affect perceived
performance - Use threads and async calls
- Understand what the APIs are doing
8.Net Compact FrameworkSpecifics
- Different than the .Net Framework
- Size and scalability
- No install time JIT (NGEN)
- GC is not generational
- No Code Access Security
- CLR
- Optimizations unavailable while debugging
- Emulator is different than real devices (ARM)
9Common Language RuntimeExecution Engine
- JIT compilers
- Two JIT compilers today
- Emulator and ARM device performance experience
may be different - Code pitching policy is different
- Optimizations (ARM)
- Method inlining for simple methods
- Enregistration
- Optimizations made unavailable while debugging
from Microsoft Visual Studio - Call path
- Properties are calls
- Virtual calls are more expensive
- P/Invokes are more expensive
- Floating Point
- Pocket PC platforms dont have FPUs
10Common Language RuntimeGarbage Collector
- What triggers a GC?
- Memory allocation failure
- 750KB of GC objects allocated
- Application going to background
- GC.Collect()
- Avoid helping the GC, dont call GC.Collect()
- What happens at GC time?
- Freezes all threads at safe point
- Finds all live objects and marks them
- An object is live if it is reachable from root
location - Unmarked objects are freed finalizers run
- GC pools are compacted if required
- Return free memory to the system heap
- In general, if you dont allocate objects, GC
wont occur - Beware of side-effects of calls that may allocate
objects
11Common Language RuntimeFinalization
- In general, you should free underlying resources
explicitly - If your object does not require finalization,
dont implement it - Overhead to call finalization
- Only one thread for finalization
- Objects that require finalization have an
extended lifetime - If your object requires finalization, implement
Dispose pattern (IDisposable) - Callers can then explicitly call Dispose to
release underlying resources - Dispose method should suppress finalization
- If the object you are using implements Dispose(),
call it when you are done with the object
12Common Language RuntimeFinalization and Dispose
- class Log IDisposable
- FileStream m_FileStream
- public void Dispose()
- if (m_FileStream ! null)
- m_FileStream.Close()
-
class LogEx IDisposable IntPtr
m_NativeResource public void Dispose()
Dispose(true) private void
Dispose(bool disposing) // Dispose
always frees native resources if
(m_NativeResource ! IntPtr.Zero)
FreeNativeResources(m_NativeResource)
m_NativeResource IntPtr.Zero
// Only free managed resources (and suppress
// finalization) if disposing if
(disposing) FreeManagedResources(thi
s) GC.SuppressFinalize(this)
LogEx()
Dispose(false)
13Common Language RuntimeValue Types
- Value types allocated on the stack
- .NET Framework primitive types are value types
(for optimal performance) - Keep value types small and simple
- Useful for items like Point (x,y coords)
- Avoid frequent boxing and unboxing
- Boxing causes a heap allocation and a copy
- Can negate performance gains
14Common Language RuntimeValue Types
- class ThreadTable
-
- Int32 m_keys
- ThreadInfo m_values
- Int32 m_cKeys
- public ThreadTable(Int32 capacity)
- m_keys new Int32capacity
- m_values new ThreadInfocapacity
- m_cKeys 0
-
- public ThreadInfo thisInt32 key
- get
- for (int i 0 i
- if (m_keysi key)
- return m_valuesi
-
- Scenario
- Application tracks threads
- Allocates one thread info object per thread
- Relatively few threads (
- Look-up to get thread information is frequent
(100,000s) - Solutions
- Hashtable, or
- Emulate Hashtable
- Key is Int32 (Thread ID)
- Hashtable is just linear lookup array
15Common Language RuntimeExceptions
- Exceptions are cheapuntil you throw
- Throw exceptions in exceptional circumstances
- Do not use exceptions for normal flow control
- Use performance counters to track the number of
exceptions thrown - Replace On Error/Goto with Try/Catch/Finally
in Microsoft Visual Basic .NET
16Common Language RuntimeExceptions
- class Log
- FileStream m_FileStream
- // Opens an existing log file
- void Open(String fileName)
-
- m_FileStream new FileStream(fileName)
-
- bool OpenEx(String fileName)
-
- if (File.Exists(fileName) false)
- return false
- else
- m_FileStream new FileStream(fileName
) -
// Calling semantics for Open void Caller1()
try log.Open(myFileName)
catch (FileNotFoundException) // Handle
error
// Calling semantics for OpenEx void Caller2()
if (OpenEx(myFileName) false)
// Handle error
17Common Language RuntimeReflection
- Reflection can be expensive
- Reflection performance cost
- Type comparisons (for example typeof() )
- Member enumerations (for example
Type.GetFields() ) - Member access (for example Type.InvokeMember()
) - Should be avoided for performance sensitive code
paths - Be aware of APIs that use reflection as a side
effect (for example Object.ToString() ) - Avoid using Type.InvokeMember()
18Common Language Runtimeversion 2 (Whidbey)
- CLR undergoing substantial re-working for
performance - Garbage Collector
- Less overhead per object
- Faster allocator
- JIT Compiler
- Better code generation
- More inlining
- Enregistration (passing locals in registers)
- Improved call path, including p/invoke
- All platforms have same optimized JIT
- Improved virtual method dispatch
19Base Class LibraryArrays and Collections
- Use strongly typed arrays where possible
- Use jagged, not multidimensional arrays
- Jagged arrays give better performance
- Jagged arrays are not in CLS however
- Presize collection classes appropriately
- Resizing creates unnecessary copies
20Base Class LibraryStrings
- Use StringBuilder class for complex string
concatenation and manipulation - Strings are immutable
- String.Concat() causes unnecessary copies
- Do not use foreach() to enumerate characters in
strings - foreach(char c in str) //use c
- Use array index
- for(int i0i
21Base Class LibraryWhidbey Performance
- String class improved
- One object instead of two
- Improved string allocation
- fixed(char p string) works!
22Windows FormsBest Practices
- Load and cache Forms in the background
- Populate data separate from Form.Show()
- Pre-populate data, or
- Load data async to Form.Show()
- Parent controls top-down
- e.g. Form ? panels ? controls
- Use BeginUpdate/EndUpdate when it is available
- e.g. ListView, TreeView
- Keep event handling code tight
- Process bigger operations asynchronously
- Blocking in event handlers will affect UI
responsiveness
23Graphics and GamesBest Practices
- Compose to off-screen buffers to minimize direct
to screen blitting - Approximately 50 faster
- Avoid transparent blitting in areas that require
performance - Approximate 1/3 speed of normal blitting
- Consider using pre-rendered images vs using
System.Drawing rendering primitives - Need to measure on a case-by-case basis
- Override OnKey methods on controls instead of
adding Key event handlers - OnKeyDown, OnKeyUp, OnKeyPress
24XMLBest Practices For Large XML Data Files
- Use XmlTextReader and XmlTextWriter
- Smaller memory footprint than using XmlDocument
- XmlTextReader is a pull model parser which only
reads a window of the data - Design XML schema first, then code
- Understand the structure of your XML document
- Use elements to group
- Allows use of Skip() in XmlTextReader
- Use attributes to reduce size
25XMLBest Practices for Serialization
- Use XmlTextReader and XmlTextWriter
- XmlDocument builds a generic, untyped object
model using a tree - Type stored as string
- Use XmlConvert to convert each element to
appropriate managed type for efficiency - e.g. Int32
- Design XML schema first, then code
- Use elements for objects and arrays
- Use attributes for simple properties and fields
26DataBest Practices
- If data is localinstead of DataSet
- Leverage SQL CE native in-proc database
- Query data using DataReader
- Use TableDirect command type for fast index
searches - Equivalent to SELECT FROM foo WHERE bar 3
- Limit open SqlCeCommand/DataReaders
- Dispose when complete
- If data is remote
- Use SQL CE replication
- When using Web Services
- Use DiffGrams to read and write DataSets to limit
data transfer - Save data locally in SQL CE for faster access and
storage - Dont save remote DataSets as XML to device
- If you do, save Schema as well
27XML and DataV2 Performance
- Vastly improved XmlTextReader (SP2) and
XmlTextWriter - XmlSerializer
- XPath
- General data improvements
- DataSet.ReadXml
- Improved ADO.NET performance with SQL CE 3.0
- SqlCeResultSet
- Direct access to scrollable, updatable cursor
28Measuring Performance
- Understand the APIs
- Micro-benchmarks versus Scenarios
- Benchmarking tips
- Use Environment.TickCount or p/invoke to high
resolution timer (QueryPerformanceCounter) - Measure times greater than 1 second
- Tools available
- Static Performance Counters (Mscoree.stat)
29Measuring Performancemscoree.stat
- Use Windows CE registry entry or .NET Compact
Framework-based sample app - What does mscoree.stat tell you?
- GC
- Simple
- Compactions
- Full
- Latencies
- JIT
- Number of bytes of native code generated
- Number of bytes pitched
- Number of Exceptions
30Summary
- Make performance a requirement
- Understand the APIs
- Reduce, re-use, recycle
- Objects
- Code
- Lazily (and asynchronously) allocate resources
- Calls Dispose on objects that implement
IDisposable
31Questions ?
- I will be posting all content on my blog
- http//www.malekkemmou.ma