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.
I 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.