Silverlight Performance Resources

Resources

Silverlight Performance Best Practices and Resources

We wanted to post a summary to Silverlight perf best practices and links to perf resources.
Please send us feedback as far as what else you would like to see posted here or if you have other links to great perf resources that you think we should be adding here.

Improve startup time:

  • Simplify your XAML
    • Reduce element count. Inspect your tree and know your tree element count using tool such as Silverlight Spy.
    • Reduce the # of properties in your XAML. If your XAML is generated by Blend for example, remove all the properties that are the default. This should improve XAML parsing time.
    • Remove "Dead XAML" that may left beyond and is no longer needed.
    • Use Templates over UserControls. UserControl re-parsed per instantiation, templates parsed only once (We have not discussed this but it is in our blog)
  • Minimize download size
    • Breakup large XAPs to smaller ones
      • Dynamically load modules not needed at app startup
    • Re-zip your XAP using a more efficient compression (e.g. 7-zip which is open source)
    • Postpone initializations, web access, etc.
      • Defer objects initialization until it is really needed (System.Lazy<T> makes this easy)
    • Do not wait on Network I/O during startup
    • Avoid loading data not needed at startup
    • Use a Splash Screen to improves perceived performance
  • Minimize Disk I/O
    • Majority of coldstart time is Disk IO.
      • Make Network download, Disk IO & CPU/JIT as concurrent as possible
    • Load fewer assemblies at startup
    • Beware of JIT in-lining. Move code that you know is not needed at startup to its own method and decorate it with "NoInlining".
      Example: since DataGrid  is not created during startup it should be moved to its own method. This will prevent System.Windows.Controls.Data.dll from getting loaded at startup!

Improve run-time perf

  • Reduce what is updated to screen
    • Silverlight will draw only what is "dirty", you can help by:
    • Avoid or reduce animations of large visuals
    • Turn off hidden animations
    • Beware of controls that animate by default such as progress bar
  • Visualize what is updated to screen
    • Set flags during debug
      • Enable RedrawRegions to see what's updating
        • <param name="enableRedrawRegions" value="true" />
        • In code: Application.Current.Host.Settings.EnableRedrawRegions = true
      • Enable FrameRateCounter to verify your animations frame-rate is not slowing
        • <param name="enableFrameRateCounter" value="true"/>
        • On lower/left status bar and on top-left if EnableGPUAcceleration enabled
  • Use Effects carefully
    • Designers love to use them, but be cautious
    • Effects have CPU & memory impact : causes allocation of additional intermediate surfaces
    • Effects are rendered in Software
      • Any object that applies an effect will also be rendered in Software
    • Avoid triggering re-rasterization
      • Do NOT animate properties of Effects
      • Do NOT apply effects to elements that frequently change (E.g. animating color)
    • Apply to smaller areas
      • Be especially watchful when Effects are applied on a large container
      • Verify container has no child elements that are updating.
        Any small animation (or even blinking caret in a Textbox) will cause constant redraw!
      • Read more in this blog: Understanding the impact of Effects on performance
  • Understands when to use the GPU.
    • Elements or trees of elements can be Bitmap cached (aka CachedComposition) and will get accelerated via GPU
      • Cached Bitmap lives on GPU memory
    • Significant perf gain for blending and transforms scenarios (e.g. Animate opacity)
    • Properties that can be GPU Accelerated:
      • Render Transforms
      • Opacity
      • Rectangular Clip
      • Visibility
      • Projections*
    • Falls into Software rendering when using:
      • Effects (e.g. DropShadowEffect) , Opacity Mask, Non-rectangular Clips
    • You can control the size (quality) of the cached Bitmap using RenderAtScale. Understand the are Memory/perf vs. quality tradeoff
      • Maybe useful when you drag/scroll your diagrams
  • Simplify your tree
    • Keep your trees smaller and flatter trees.
      • Less memory consumption (less allocations, GC , paging, etc.)
      • Events that traverse smaller/flatter trees are much faster
      • Less blending by the graphics pipeline
    • Know your element tree count
    • Use Templates over UserControls. UserControl re-parsed per instantiation, templates parsed only once (We have not discussed this but it is in our blog)
    • Use Silverlight Spy to inspect your tree
    • Remove sub-trees no longer used (Login & Welcome dialogs often left unused).
      If you must, use Visibility="Collapsed" over Opacity="0"
      Collapsed elements not blended, don't participate in input events, etc bt they do consume memory.
    • Consider removing large sub-trees in chunks not to block the UI thread
    • Virtualize your canvas and lists. Remove or skimpily elements that are not legible when you zoom out.
      • Check Visual Studio 2010 Ultimate DGML viewer perf (open these Demos in VS10 Ultimate)
        VS2010 uses many of the concepts that are discussed in CodeCanvas and ZoomableCanvas series of blogs. Although the code samples are for WPF it should relative easy to port to Silverlight.
  • Avoid blocking the UI tread.
    • Use BackgroundWorker or Dispatcher.BeginInvoke() for long running/blocking operations. (Sample in our Silverlight Firestarter resource below )

Reduce Memory usage

  • As mentioned earlier sampling the visual tree, keep element count low, virtualize where possible.
  • Be aware of high resolution images
    Always decode the image to desired size and not to the default size. You will reduce not only your application's working set, but execution speed as well.
    WPF has DecodePixelWidth however, Silverlight does not have this API, however you can work around this by using WriteableBitmap, see more in this blog: Silverlight's Big Image Problem (and What You Can Do About It)
  • Use tools to understand your application memory
  • Avoid memory leaks

Useful tools & resources