#1 – Reduce or eliminate view state
View State is not your friend when it comes to page performance, so if you do not need it (as in your page does need to persist data between page requests), then do not use it at all. This is especially true for pages that will run on the Salesforce1 mobile platform!!!
How do you not use it all?
Do not include the <apex:form> tag unless you absolutely have to. This tag should only be used when you are accepting input from the user, so if you are only displaying data to the user, you should not have a form tag.
Like this Post? Then you will really like the “Improving Visualforce Performance” course that I designed for lynda.com. It was based on this post specifically and goes into great detail about each one of the tips in this post. Check it out!
And, even if you are accepting input, it is likely that not all the data on your page needs to be submitted through a POST request. For example, you could have a page that lists some account data, but only allows the user to change one particular field. In cases such as these, you could use the Transient keyword in the Controller class to make all the data fields (and especially collections) that are not being changed read-only. This means they will not be stored in the view state and your page will load faster.
#2 – Evaluate SOQL for Efficiency
There are several ways you can write better SOQL code. For starters, ALWAYS make sure you place SOQL queries outside of loops. This should be done no matter what. It will not only make your page perform better, but will help avoid limit errors and should be standard practice. This also applies to DML.
Beyond that essential tip, you should also consider:
- Only return fields that you are using on the page
- Use WHERE clauses as much as possible to restrict the number of records returned
- Use indexed fields in your WHERE clause as it will make the query optimizer work better. Default indexed fields are Id, Name, Owner, LastModifiedDate, and any foreign key or ExternalID fields.
- Use the LIMIT keyword when possible
- Use aggregation functions such as COUNT()
- Use the WITH SHARING keyword in your controllers since the sharing architecture is used by the Query Optimizer and you will only retrieve the records that the users has access to
- Additional suggestions (per reader JSON Hammerle) are to:
- Use native (more selective indices) when possible
- Hash your composite key (if you have one) into the native name field and use this hash in your WHERE clause This is comparable to a skinny table but you don’t have to work with support – and it can be delivered in a managed package.
- Order your WHERE clause from most selective to least
#3 – Reduce use of Action tags
This kind of goes with tip #1, but since it is so important, I wanted to make it a separate point. Action tags such as <apex:ActionPoller> and <apex:ActionFunction> seem great on the surface since they are VERY easy to use, but they are memory hogs, so limit your use of them and consider alternatives.
Rather than using the ActionPoller tag, you should consider using the Streaming API. It means more code for you, but it results in no view state (remember tip #1). If you do not like the Streaming API, then consider using traditional polling using a Meta tag with a refresh and a window.location.reload.
#4 – Take Advantage of StandardSetControllers when dealing with lists of data
StandardSetControllers, which are used to create list controllers are your friends and you should use them whenever possible. The StandardSetControllers are optimized to work with large data sets of up to 10,000 records and include pagination features (which you should be using) automatically. There is no need for you to do this yourself.
When you do use them, instantiate them using a list of sObjects instead of from a query locator, as this is a more efficient way.
- Remember less is more and smaller is better.
- Files should be minified and use Static Resources
- Avoid using global variables
- Use browser caching when you can
- Avoid use of iframes
There are tons of documents out there about best practices. Two of my favorites are:
7 thoughts on “Top 5 Tips for Improving Visualforce Pages”
This blog has so many good tips that i had to share with my teammates. Thanks a lot for sharing. On point #2, a couple other ideas would be to use native (more selective) indices when possible. Another technique is to hash your composite key (if you have one) into the native name field and use this hash in your where clause. This is comparable to a skinny table but you don’t have to work with support – and it can be delivered in a managed package. Last suggestion is to order your WHERE clause from most selective to least. I hope to find some time to benchmark variations and then blog about it in the near future. Thanks again!!
Thanks Jason. Actually, I was thinking about doing the benchmarks just as you suggested. I will definitely do it now. I am working on a course about Visualforce for lynda.com and that would be some GREAT material to add to it (as well as to post on my blog).
Thanks for the other suggestions. I will add those to the post.
When you benchmark the SOQL then you may consider working with Salesforce Support to obtain the logical reads instead of using the actual time elapsed. Not 100% sure they would be willing to provide that information, but it would be a much better comparison. And you’d have more content for your blog and course.
Good idea. Thanks again Json!
I really liked your blog. It has some really good point which i didn’t even think or know about. Thank you for great post.