Friday, 18 September 2015

Dynamics CRM 2011/2013 Investigating CRM Form Performance issues

Performance in CRM is only a problem when performance is a problem 

I have been doing some work on performance of some CRM forms in CRM 2011.  When the topic of performance crops up people the topic of when you should focus on performance won’t be far away.
I’m assuming you haven’t put in the terrible performing code, customizations or processes and you have tidied/refactored customizations to a good standard.   In this scenario I only look into improving performance if there is a problem with performance or the customer isn’t happy with performance.
I can hear some of you thinking
Isn’t it better to make your CRM system run as fast as possible? 

Yes of course it is, a faster CRM system is better than a slower a CRM system but is this a priority to the customer. If the customer is happy with the speed of the CRM system and the current customizations then the customer would benefit more from a system with less bugs and/or have more functionality they would like.
The cost of spending time on optimizing your Microsoft dynamics CRM solution can take quite a long time for a small benefit of a second or half a second on some forms.
Law of diminishing returns
The usual process of optimizing solutions in CRM is there are some big performance gains in maybe 10 percent (or lower) of the CRM system, these can be found usually in
  • Code
  • Configuration
  • Business process.
After the initial great gains the effort increases and the reward (time saved) gets smaller and smaller.
I like to think of the law of diminishing returns as the bacon sandwich conundrum.  Ibacon sandwich is magnicant but the second bacon sandwich  is ok, additional bacon sandwiches get lower on the tastometer, which is a crime agaisnt bacon sandwiches.
digress because this blog post is about the performance of Forms in CRM 2011.

Focus on the slowest forms
In a CRM system there are lots of forms you can look at improving the performance of, so where should  you start. The main forms you should concentrate on
The slowest forms
The most used forms which are slow
The forms you should focus on first are the slowest forms because these have either the biggest problems or the most problems.  The worse performing forms are likely to have the biggest gains.
The way I have been doing this was seeing how long it took the forms to load and what traffic
Common Culprits of slow form loading
The main culprits of slow loading forms are
  • Busy Javascript onload functions
  • Too many subgrids
  • Lots of oData/fetchXML queries
  • Tabs, sections and fields not needed on the form
  • bad/slow coding
To start the code optimization, the first step was to find the bottlenecks and worst performing forms.  The next step was to get a benchmark to see how they were loading, to get an average we loaded the form 5 times and the results were quite varied.
We had our list of worst performing forms and we had a quick look at them and made some quick notes
  • How many unfiltered OData retrieves
  • How many OData calls, where they retrieving the same set
  • Number of ribbon buttons
  • potential fields/functionality which could be removed by change of business process
  • size of Javascript onload function

Tactics – finding those slow form
Fiddler
One of the tools I used to analyize the slow loading CRM forms was fiddler.  I wrote a blog post about Getting Started with Fiddler and CRM.  It’s a great tool to see what calls are being made from the page, how long they took and how much data they were bringing back.
Looking at the fiddler logs I was able to investigate the OData queries and find
  • Which OData calls took the longest
  • Find OData calls which were not filtered
  • Find OData calls which were retrieving the same data multiple times
  • general loading times of sections of code
F12 Debugger
The F12 debugger is such an awesome tool for debugging Javascript.  I put in a break point in the onload Javascript and walked through the code.
We are using two main methods to find slow loading code
Looking at the code
Stepping through the code
 How to speed up form loading
Does the customer/end user need all the functionality and fields on the form
Ask the customer to re-evaluate the fields and functionality on the forms.
In some of the forms we were retrieving fields from related entities but to speed up the form the customer was happy to use lookups and click those for more information if it was needed.   This saved OData queries
When the carrot of improved performance is offered, end users are often more willing to move functionality from Must Have status to Nice to Have or not needed.  These changes can remove some of the code triggered on the Javascript onload.
Improvements can come from moving fields and subgrids into unexpanded tabs where the loading can be delayed until the tab is expanded
subgrids
Subgrids take time to load and the more subgrids you have on a form the longer it will take to load.
Form load time can be saved by putting the grid in an unexpanded tab, this will not load the grid on the form load but will load it when the user expands the tab.
Remove unwanted/unused fields
CRM Developers have to refactor their code then I think CRM Forms and entities should be refactored to remove the noise of unused fields.
There is a great tool to help you with this called CRM Data Detective it will show you what fields are being used/not used by seeing if any values were written to those fields.  The CRM Data Detective is a free tool which works with CRM 2011 and CRM 2013.
OData queries
OData queries are a great way to retrieve data from related fields but if a form has a lot of them they can slow it down.  If you use OData queries makes sure they are as lean as possible by filtering them.  Below are some tips for using OData queries
  • ALWAYS filter your OData queries to retrieve only the fields you need
  • Group OData queries to avoid multiple OData queries
  • Cache the return data in a Javascript variable if different functions need the same data
Code Logic
Often the first step in writing code is getting it to work, so I can forgive initial code to look ugly and speed along like a one legged tortoise.
It’s unforgivable for the CRM developer not to refactor this code.  CRM developer should keep their standards high and not slack off adding dodgy code but this is very frustrating to other team members who will then have to dry and debug it and find it very difficult.
Unrefactored code creates technical debt and this will have to be paid at some point.  You don’t save time but putting in sloppy code, you cost the team more time later when debugging and extending that code will take a lot longer than it would if the code had been refactored.
How to avoid slow code
Peer reviews
Developers code improves by about 70 percent when they know someone else is going to review it (a statistic I just made up but 100 percent true). I’m not saying Developers can be lazy but often time restrictions and a promise tidy the code up later (which rarely happens) will allow some basic poor coding to slip in.
If a developer knows someone is going to scrutinise their code (or even the threat it) the developer finds time to refactor the code because if hey don’t they know it will be looked at and then told to tidy it up.
Peer reviews can be seen by some developers as a bad thing but it’s a good way to learn new programming techniques and best practices.  The ultimate benefit is having more eyes look at some code will stop a lot of bugs sneaking in and keep coding standards high, both of which will benefit the project in the long term.
This article has Developer’s guide to peer reviews highlights some of the benefits
  • A different perspective. “Another set of eyes” adds objectivity. Similar to the reason for separating your coding and testing teams, peer reviews provide the distance needed to recognize problems.
  • The ability to assess and accelerate progress. Is the team producing the needed output at the needed rate?
  • Pride/reward. Recognition of coding prowess is a significant reward for many programmers.
  • Project/module familiarity. Everyone involved in the review becomes more familiar with the project and the module.
  • Less rework. Do it right the first time. Changes cost more later in the life cycle. The peer review process catches many errors before they go to production.
  • Fewer bugs. It’s better to discover your own problems than to have someone (like a user) point them out to you. For the same reason, you may find that many bugs will be eliminated before the code comes to be reviewed by peers.
  • Improved communication. More opportunities for interaction tend to lead the team toward improved communication.
  • Team cohesiveness. Working together helps draw team members closer. It also provides a brief respite from the isolation that coding often brings.
Coding standards
Companies should coding standards, otherwise the worms are well and truely let out of the can and once those worms are out it’s very hard to get them back in.
Creating coding standards lets the developers know they are expected to code to a standard and there is no excuse for the developers not knowing what the standards are.
Coding standards will also resolve conflicts of style because everyone is expected to code to the agreed company standards.
When I was a Java developer I use to love have my bracket on an If statement on the next line
IF
{
}
when Microsoft and other standards have it like this
IF {
}
This is a minor point but when you are looking at 1000’s of lines of code it can make a difference, particularly when it’s not just this small change but lots of others.  Suddenly you are in a situation where one persons code is formatted (with different variable names) completely differently making it harder to read, understand, debug and extend the code later.

Coding standards documents are great gift to new developers starting (and then constantly referring them to :-)) because it highlights how they are expected to write code and potential feedback from peer reviews.
Coding standards will help create code consistency not only between different developers but also between projects, which makes it easier for developers to switch between projects.
Common Libraries
CRM makes it easy for CRM Developers to write the same piece of code in every Javascript file on every entity and the same code in multiple plugins.  Code duplication is bad practise, it increases not only the possibility of bugs (e.g. updating code in one place but not the other duplicates) but also increases time to fix a bug because you have to make the change in all the places the code is.
Stop writing the same function in each javascript file for each different form.
Create common libraries then it only has to be written once (and well) and then used again and again.
The advantage of writing code once and used in many places is easy to maintain, debug and extend and you only need to test it once.
if there is a bug you only have to fix it one place.
Sometimes it takes more time to generalize a method but in the long run it will save you time.
Why have I put this in a blog about form loading, if you optimize this code it will save time in all the CRM forms it’s used.
Always filter queries
There is no excuse for getting all the fields back in a query because you never use all the fields and the CRM developer is just being lazy.
There are lots of retrieve code in CRM, it can be found in plugins and Javascript but make sure the developers filter, always.

Split loading times
Evalulate if you need all the data and checks to be done on the form load.  It’s possible you could move some of the functionality to
  • Unexpanded tabs
  • Onchange events
 Unexpanded Tabs
You can put a subgrid in an unexpanded tab and load the subgrid when the tab is expanded.  If you have optionsets or other fields which need to be calculated using retrieved fields then these can also be triggered on expanding the tab. This saves time from the form loading.
This would also save time if the tabs included Maps and iFrames.
OnChange Events
For some functionality it might be possible to delay some code and remove it from the form onload to a field onChange event.
 Javascript files
You can minify Javascript files which shrinks the size of the file and load quicker
There may be some performance gains from combining 2 or more Javascript files into one Javascript file
Plugins/Workflows

Similar to moving Javascript functionality from OnLoad to OnChange events it maybe possible to move some functionality to Workflows and plugins on the save of a record.  In general plugins run faster than Javascript.

Thursday, 17 September 2015

Scripting on Business Process Flow in CRM 2015


With the introduction of MS CRM 2015, came many new features. The one we are going to discuss here is advancement of Business Process Flow and especially the Scripting part, which came as boon.
Before CRM 2015, the Business Process Flow exist, but no API availability made it impossible for the developers to interact with the BPF via programming.
CRM 2015 gave it a new look, while creating a Business Process Flow, we have the option of creating Branched stages, which in simple terms is we can conditionally decide which stage to be shown after the current stage. The branching decisions can be made on the basis of the value of any step used for the current stage.
Previously we were not allowed to visit an entity more than once before, now we can visit an entity more than once.
Above are the few highlights of features added for BPF, let`s delve into the Programmability enhancement.
The most important part is, How to hook to the Stage change or Stage Select events of BPF? This is indeed the simplest part.
Example:
If you want to hook to the Stage change event, you can do this by writing the below code. And, you have the freedom to place this code either onLoad or onSave of the form or else on change of any field.
//Register a function on change of the stage
Xrm.Page.data.process.addOnStageChange(stageChange);

stageChange – It is the function to be called when the stage is changed.

Similarly, you can hook onto the Stage select event.
//Register a function on select of a stage
Xrm.Page.data.process.addOnStageSelected(stageSelected);

stageSelected – It is the function to be called when the stage is selected.

We have the options to unhook the events as well.
//Unbind a function on change of the stage
Xrm.Page.data.process.removeOnStageChange(stageChange);
//Unbind a function on select of a stage
Xrm.Page.data.process.removeOnStageSelected(stageSelected);
By hooking onto either stage change or stage select events, we have plethora of options to use.
Like we mentioned above, that we can Branch the entities conditionally. We can leverage this functionality by showing different fields for an entity depending on the value selected for the step on the previous stage.
Let us explain you few of the available methods in this part of the Blog, and the rest in this.
  • Collapse or Expand the Business Process Flow:
We have the option to collapse the Business Process Flow by default, on load of the form.
Snippet:
Xrm.Page.ui.process.setDisplayState(string)
string: “expanded”  or “collapsed” are the two variables that can be passed.

  • Show/Hide the Business Process Flow:
We can show or hide the business flow. It can be useful when we don`t need few of the Security Roles to see the BPF.
Snippet:
Xrm.Page.ui.process.setVisible(bool)
bool: “true” to show and “false” to hide.

  • Active Process:
We can get the Current Active Process and we can set the Current Active Process. This is useful if you want different security profiles to see different processes.
  • getActiveProcess
This will give you the object of the current Active Process. Object will have,
Process Name, Process Id(GUID), Render State(Visible/Hidden) & Collection of Stage Objects.
Snippet:
var procObj = Xrm.Page.data.process.getActiveProcess();
  • setActiveProcess
This will allow you to set the Active Process.
Snippet:
Xrm.Page.data.process.setActiveProcess(procGUID, callbackFunction);
procGUID: Id of the process to be set.
callbackFunction: Function that will be called in order we have any necessary actions to be performed on setting the process.

  • Active Stage:
We can get the Current Active Stage and we can also set the Current Active Stage. This is useful if you want a user to move back to previous stage, when he selects “x” value for a step on current Active stage.
  • getActiveStage
This  will give you the object of current Active Stage. Object will have, Stage Name, Stage ID(GUID), Base Entity, Stage Status(active/inactive) & Collection of Step objects.
            Snippet:
var actStg = Xrm.Page.data.process.getActiveStage();
  • setActiveStage
This will allow you to set an Active Stage.
Note: Only completed stage for the current entity can be set using this method.
            Snippet:
Xrm.Page.data.process.setActiveStage(stgGUID, callbackFunction);
stgGUID: ID of the stage to be set.
callbackFunction: If in case any actions are to be performed after setting the Active Stage.

  • Get the Active Path
We can get the Active Path i.e., serves the exact seq. of stages that got the user to where he is now, the stage he is on and the predicted set of future stages on the basis of Branching rules.
Snippet:
var stgColl = Xrm.Page.data.process.getActivePath()
  • Get the Enabled Processes
We can get the list of enabled processes for a particular entity which user can use to switch.
Snippet:
Xrm.Page.data.process.getEnabledProcess(callbackFunction(enabledProcesses))
callbackFunction(enabledProcesses) :  This callback function will accept a parameter. The parameter will be an object having the list of enabled processes.
  • Navigate Previous or Next
What if you want to move the user next or prev depending on the value of a step on the current stage, to make that happen, we have 2 functions:
  • moveNext:
This will move the user to the next stage.
Snippet:
Xrm.Page.data.process.moveNext(callbackFunction)
callbackFunction: The callback function can be used to perform any actions that needs to be done after moving the user to the next stage.
  • movePrevious:
This will move the user to the previous stage.
Snippet:
Xrm.Page.data.process.movePrevious(callbackFunction)
callbackFunction: The callback function can be used to perform any actions that needs to be done after moving the user to the previous stage.
  • Process Methods
In the first part of the blog, we discussed how to retrieve Active Process. Now, let`s see how to retrieve the properties from the returned object.
var procObj = Xrm.Page.data.process.getActiveProcess();
  • Get the Id:
procObj.getId();
Returns a string.
  • Get the Name:
procObj.getName();
Returns a string.
  • Get the Stage Collection:
procObj.getStages();
Returns the collection of stages
  • Check whether the process is rendered or not:
procObj.isRendered();
Returns a bool.

  • Stage Methods
In the first part of the blog, we discussed how to retrieve Active Stage. Now, let`s see how to retrieve the properties from the returned object.
var actStg = Xrm.Page.data.process.getActiveStage();
  • Get the Category:
actStg. getCategory().getValue();
Returns an integer value of the Business Process Flow category.
  • Get the Entity Name:
actStg.getEntityName();
Returns the logical name of the entity.
  • Get the Id:
actStg.getId();
Returns a string.
  • Get the Stage Name:
actStg.getName();
Returns a string.
  • Get the Status:
actStg.getStatus();
Returns “active” or  “inactive”.
  • Get the Steps:
var stpColl = actStg.getSteps();
Returns collection of steps.
  • Step Methods:
In the previous point, we got the step collection. Now, let`s see how to retrieve the properties from the returned object.
  • Get the Logical Name:
stpColl.getAttribute();
Returns the logical name of the step.
  • Get the Name of the step:
stpColl.getName();
Returns the step name.
  • Get the Required Level:
stpColl.isRequired();
Returns a bool.
All these are new addition in the CRM 2015 box and those are the most asked and helpful additions. We can achieve many things by hooking onto stage change and stage select events.