Best Practices for Visualforce Page PerformanceThis past week I presented a webinar, Mastering Force.com: Advanced Visualforce, webinar which focussed on improving page performance within your Salesforce1 applications. Visualforce page performance can be affected by a number of factors which developers should be aware of. Many of the conversations around this focus solely on the viewstate and trying to reduce its size to enable pages to load faster and to send less data in the request cycle. As part of the webinar other areas that are often neglected or forgotten about were also discussed including apex functions, loops, SOQL queries and DML statements. All the code for the demos is available on Github and the slides and recording can be found here. In this post we will review some of the tips presented to help you get a flavour of the tips presented in the webinar.

Using the Transient Keyword

For any items in your page controller that are not needed between requests you should mark the data member as transient. Marking a member as transient will ensure it is not serialized and stored in the viewstate, lowering the amount of data transferred in the page rendering.

In the demo we saw the following controller:

public with sharing class AdvancedVFTransientController {

public Contact con {get; set;}
public Account acc {get; private set;}
public List<Contact> contacts {get; private set;}

public AdvancedVFTransientController() {
con = new Contact();
acc = new Account();
contacts = new List<Contact>();
}

public PageReference retrieveInformation() {
if(con.AccountID != null) {
contacts = [SELECT Name, Id, Email, Phone, AccountID FROM Contact WHERE AccountID = :con.AccountId];
acc = [SELECT Description, AccountNumber, AnnualRevenue, NumberOfEmployees, Rating, Website, Type, NumberofLocations__c FROM Account WHERE Id = :con.AccountID];
}
return null;
}
}

This controller is attached to a page that uses an inputField on the con.AccountID field to enable users to simply select an account and then retrieve details for the account and a list of all the related contacts.

We can improve this controller by marking the “acc” and “contacts” variables as transient as they are not needed between requests (they are in fact changed every request depending on the selected account). We can see this improved controller below:

public with sharing class AdvancedVFTransientController {

public Contact con {get; set;}
public transient Account acc {get; private set;}
public transient List<Contact> contacts {get; private set;}

public AdvancedVFTransientController() {
con = new Contact();
acc = new Account();
contacts = new List<Contact>();
}

public PageReference retrieveInformation() {
if(con.AccountID != null) {
contacts = [SELECT Name, Id, Email, Phone, AccountID FROM Contact WHERE AccountID = :con.AccountId];
acc = [SELECT Description, AccountNumber, AnnualRevenue, NumberOfEmployees, Rating, Website, Type, NumberofLocations__c FROM Account WHERE Id = :con.AccountID];
}
return null;
}
}

Although this is a simple change, we can see in the recorded demo that this removed almost 25% of the page’s viewstate. The page we have does not currently need to worry too much about the viewstate, but with a larger account or more complicated page, changes that seem small like this can have big implications.

Apex in Action Functions

Many developers neglect their Apex code when trying to improve the performance of their pages. If the apex function called in an action is slow, this will make your page render or re-render slower as the user has to wait for the apex function to finish executing before the page updates. With a CPUTime limit of 10 seconds, if you take full advantage of the governor limit this can cause your page to run very slowly for a user.

Some particular items within Apex to focus on are SOQL queries, loops and DML. Performing multiple queries without correct filtering can cause your function to run sub-optimally and in particular wherever possible you should try to reduce the number of queries made. Similarly when looping over records (for example for extra processing or to populate a wrapper class for display), be careful to optimise your loops as much as possible. This can be done by initialising them in a more performant manner (see http://goo.gl/mR5GZe) and by moving calculations to queries wherever possible.

Asynchronous pages

Sometimes the best option is to make your page utilize asynchronous apex for certain functions or become asynchronous through the use of a tool such as Javascript Remoting or Visualforce Remote Objects. Visualforce Remote Objects is a newer tool in the Salesforce developer’s toolkit allowing you to define a model for your page’s data that you can interact with through JavaScript. In the webinar a demonstration of this was shown and I highly recommend that you also check out the recent “Javascript Integration With Visualforce” webinar to see how you can utilise Visualforce Remote Objects with frameworks such as Angular.js.

A Balancing Act

Page performance in Visualforce is a practice of combining multiple different best practices in order to deliver the best performance. There are many great blog posts and resources out there which detail different practices and patterns to do this. Hopefully you have learnt something from this post and the webinar. If you have any tips or tricks as well please share them below and as always, comments and questions are welcome.

tagged Bookmark the permalink. Trackbacks are closed, but you can post a comment.
  • Alfian Busyro

    Hello.

    Hmm.. I have tried your transient keyword example.
    The un-transient date only would not changed after I press button.
    If I press browser refresh or go back and forth between pages, then the date1 value was also changed (same with date2).

    Could you please add more detail for “transient” keyword ?

    • Bennie

      Something which is updated and not stored should be marked as transient.
      The controller variables which are not set from controller but are
      getting displayed from the controller is good piece of data to mark as
      transient. Not always but normally the variables which are marked as
      {private set;} should be marked as transient.