Understanding the Microsoft Dynamics CRM Performance Center

Note: I originally posted this at cobalt.net

The Microsoft Dynamics CRM Performance Center is a fantastic addition to CRM which can help you troubleshoot performance issue related to loading forms in CRM. I’ve found a few online references about the CRM Performance Center but they all focus on how to access it and don’t really give you context for interpreting the results. This is my attempt to combine the diagnostics messages with other CRM materials (Microsoft Dynamics CRM 2013 Updated Form Performance, http://blogs.msdn.com/b/crm/archive/2013/10/31/microsoft-dynamics-crm-2013-updated-form-performance.aspx) in order to make the Performance Center more helpful for the CRM community.

Starting the Performance Center

The Performance Center is available in CRM Online and CRM OnPremise 2013 SP1 or higher. The performance center doesn’t seem to work in Chrome (the browser closes with the key combination), but IE 8+ works fine.

To enable the Performance Center:

  1. Open a form that you want to benchmark
  2. Hit Control+Shift+Q to open the Performance Center window
  3. Click ‘Enable’ to start logging, and then ‘Close’

performance center 1

  1. Refresh the form and open the performance center again
  2. Verify the benchmarks are now loaded
  3. Click ‘Select Major’ to get a summary of milestone.

performance center 2

  1. When you’re done with the Performance Center, make sure to click ‘Disable’ to stop the logging, so you aren’t adding additional overhead.

Diagnostic Messages and Associated Events

Diagnostics Message: Form Load Start (→ 0ms)

  1. The diagnostics timer starts and form initialization begins
  2. The form load bootup process starts, which requests entity instance data, configuration information, CSS, and Javascript tags from the CRM server.
  3. Entity metadata and the form retrieval – The layout is retrieved from the browser cache
  4. Data binding and building the read ready form – The form layout and record data from the previous two steps are built and displayed to the user. All of the fields and their data are visible but they aren’t editable yet. This state is called View Ready, or Read Ready.

Diagnostic Message: Read-Ready (→ 931 ms)

  1. Transitioning the form to edit ready – The form downloads any additional Javascript which has logic for any controls on the form. The Javascript is executed in order. Individual field controls are initialized.
  2. Social pane and Inline subgrids initialization – In this stage, data is pulled from related records for display in the Social pane or subgrids on the form.
    • Expanded grids in the current viewing area are loaded
      Diagnostic Message:  Initialize Controls – ViewportInlineEditControlInitializer (→ 2452 ms)
    • Expanded grids off the current viewing area are loaded
      Diagnostic Message:  Initialize Controls – NonViewportFormBodyInlineEditInitializer (→ 2567 ms)
    • Collapsed grids are loaded
      Diagnostic Message:  Initialize Controls – DeferredQuickFormInlineEditInitializer (→ 2778 ms)
    • Load the Social Wall
  3. The Form’s OnLoad event is executed

Diagnostic Message:  Form Full Controls Init (→ 3390 ms)

At this stage, the form is completely editable. Clearly there are a lot of moving parts when it comes to rending a single form in Dynamics CRM.

How to Improve Performance

The messages can be a bit misleading because a lot of the events are handled, at least partially, asynchronously. For instance, grids can begin to load in step 6.a, but there’s another event “CompleteInlineEditInitialization” that runs parallel with loading the social wall in 6.d. I think the general approach should be to minimize that critical path of code that must run synchronously.

Before getting into specifics improvements, one easy way to help load time is to simplify what’s available on the form. CRM can be such a powerful tool that sometimes we might get carried away and try to just show everything possible on each form, at the expense of performance and really, user experience. If you’re judicious about what you’re showing then every step could be quicker.

Between initialization and read-ready
The two primary actions here are retrieving the record from the database, and merging that with the HTML template for the form. The big gain you can get here is just from reducing the number of fields that need to be handled. If you have a plugin registered on the Retrieve event of the entity, that time would be logged here, so you may want to look at optimizing you plugin step as well.

Between read-ready and Initialize Controls – ViewportInlineEditControlInitializer
The two big actions here are downloading and running field Javascript and loading expanded grids in the current viewing area.

To reduce time associated with loading and executing Javascript, you can follow a number of best practices described in the article Write code for Microsoft Dynamics CRM forms, available at http://msdn.microsoft.com/en-us/library/gg328261.aspx . Best practices include:

  • Avoid including unnecessary JavaScript web resource libraries
  • Avoid loading all scripts in the Onload event
  • Use collapsed tabs to defer loading web resources

I can’t find any firm references online, but from talking with other CRM developers the consensus is that collapsed Subgrids load more asynchronously than expanded Subgrids. Since they’re collapsed, the form only has the header to render because they records aren’t needed until the grid is expanded.  Based on the diagnostics messages, it seems like the most intensive grids to load are:

  1. Expanded grids in the current view
  2. Expanded grid outside the current view
  3. Collapsed grids

If you’re seeing large times in this area, you may want to look at changing grids to be collapsed, or at least lower down the page. Either way, you should see a reduction in the critical path to loading a page.

Another approach here is to limit the columns that are displayed in the grids (not just the count, but the logical location of the records). If you’re on an Account record looking at the names of associated Contacts, you’re touching one table for the contact info. If the contact grid also includes address information, now you’re linking to both the contact and customeraddress table and your query will take longer to execute.

Between Initialize Controls – ViewportInlineEditControlInitializer and Initialize Controls – NonViewportFormBodyInlineEditInitializer
It seems like most of the time in this section is for loading expanded grids off the current viewing area. As I mentioned before, these can either be collapsed or removed completely to speed up load time.

Between Initialize Controls – NonViewportFormBodyInlineEditInitializer and Initialize Controls – DeferredQuickFormInlineEditInitializer
Since the times here are for initializing collapsed grids, there’s not much you can do to speed up this stage besides removing the Subgrids altogether.

Between Initialize Controls – DeferredQuickFormInlineEditInitializer and Form Full Controls Init
The form Social Wall is loaded and the forms OnLoad event is executed. If you’re seeing excessive slowness here you can try to limit what’s on the Wall or remove it altogether, or dig into your event code to look for inefficiencies in either the script logic or even what’s loaded (see Write code for Microsoft Dynamics CRM forms above).

Conclusion

Microsoft Dynamics CRM is an incredibly extensible and customizable tool, but with that freedom comes a potential for performance issues. By removing unnecessary form fields and optimizing Subgrids, we’re able to speed up performance and give a cleaner, crisper user experience. Although there will always be some minimum load time for forms, if we’re selective about what we present and how it’s presented, we can greatly enhance the user’s experience and increase overall satisfaction.