Over the years I’ve created hundreds, if not thousands of Visualforce pages on Salesforce and I’ve learnt a lot on how to ensure users get fast responsive pages.
In this post I want to walk through some of my tips and tricks to speed up your Visualforce pages.
Amount of data
It might seem quite obvious, but reducing the amount of data your page has to load is an effective way to help improve your page load times. Often I’ve seen pages loading far too much data which is beyond what the end users actually need.
This extra unneeded data is not only costly to load from the database, but also adds to the overall size of the page which the user has to download.
Some ways you could achieve this are:
- Load only the necessary fields required for the page.
- Reduce the number of rows being returned from any queries you run.
- Use pagination to allow the user to navigate through a data set.
- Investigate with the end users again what data they actually need and not want to do their job.
View state
When you use a custom extension or even a custom controller with a Visualforce page you’ll be using the view state. All of the properties used in your controller will be stored in the view state and it is sent to the browser when the page loads.
The purpose of the view state is to reduce the servers memory usage by storing the data in the page itself. It’s a really smart way to keep the severs running fast with the trade off that the data must be stored within the page and the user must also load this.
So as I’ve mentioned just above, the trade off is that the user needs to download the view state when the page loads. But is that the only problem? Nope. Another useful feature in Visualforce is using rerender’s to perform AJAX call outs to the server to re-render a section of the Visualforce page with new content. Each time a rerender takes place the complete copy of the view state is also sent back to the server with your request.
How do we make improvements? Simple, we keep the view state as small as we possibly can.
The first step is to first analyse our controller to see what does and does not need to be maintained in the view state. For example, we don’t need to keep picklist select options in there, but we do need to maintain the selected value from the picklist the user selected.
public class MyClass { public List<SelectOption> options { get; set; } public String selectedValue { get; set; } }
When you have an understanding of what doesn’t need to be in the view state we can now modify our code to instruct Visualforce not to store specific properties in the view state. This is done by using the transient keyword.
public class MyClass { public transient List<SelectOption> options { get; set; } public String selectedValue { get; set; } }
JavaScript remoting
One way to really speed up your pages is to utilise JavaScript remoting instead of using the traditional rerender’s. What makes JavaScript remoting so much faster is that it’s completely stateless, meaning that you need to send all data back to the method and reload everything you need. The view state isn’t used at all.
It’s best used to help enhance traditional Visualforce pages such as autocomplete inputs or even for single page applications, perhaps even in combination with AngularJS.
Below is an example on how you can use JavaScript Remoting to retrieve a list of accounts.
public class MyClass { @remoteAction public static ListList<Account> loadAccounts(){ return [SELECT Name FROM Account]; } }
<apex:page controller="MyClass"> <div id="output"></div> <script> MyClass.loadAccounts(function(result, event){ var names = ''; for(var i=0; i < result.length; i++){ names += result[i].Name + '<br/>'; } document.getElementById('output').innerHTML = names; }); </script> </apex:page>
The downfall to using JavaScript remoting is that you will need to write all custom JavaScript and implement new Apex remote actions to handle the requests from the page, however once done you’ll really see a dramatic increase in responsiveness. It can be sometimes difficult to mix together standard Visualforce functionality with JavaScript remoting, so you may need to think how you will combine the two if required.
An alternative approach is to use the newer, but less flexible remote objects in Visualforce. The functionality is very similar to JavaScript remote objects but is intended to be a simple JavaScript interface for performing CRUD operations on sObjects directly without requiring Apex. Again, this approach doesn’t use the view state and also is stateless.
Optimising your queries
Optimising queries is an important aspect to improving performance as the less time we spend retrieve data the faster we can get the page back to the user. Even if your queries are loading reasonably quick there are steps which can help get even better response times from the database.
It’s a rather large subject to cover and Salesforce has plenty of documentation on this. Find below some useful links to help you get started in this area:
Apex speed
The speed of your Apex code can also really effect how fast your page loads.
Some tips to having fast Apex are:
- Remove unused code.
- Be careful with loops and especially nested ones.
- Try to use a do while loop instead of using recursion.
- Select the right type of for loop for the given task – more on this in a moment.
- Remove unncessary debug statements added during development.
- Replace older utility methods with newly added code provided by Salesforce. For example, the String class has had major updates for which older org’s may have written their own versions of.
- Avoid after insert and after update events in triggers unless you absolutely need them, they really slow down your application.
One area you can really improve the speed in is for loops. Check out the following video comparing the different for loops available and also how they compare in performance.
You can find part 2 of the video below.
Platform caching
It’s definitely one of the best tools to utilise to get incredibly fast applications in Salesforce!
In most applications there is often a set of data which is reloaded in most pages and or even in batch jobs. This data can be specific to individual users or data which is used by all users.
Enter platform caching.
Platform caching is still relatively new only arriving a few releases back, and it’s a much needed addition to the ecosystem. It enables developers to programmatically place data into memory partitions specific to either the current user or the organisation. Developers can then retrieve the cached data from memory instead of having to requery or rebuild complicated data structures again and again.
My experience with Platform Caching overall has been really positive and I’ve seen my response times decrease from a few hundred milliseconds up to seconds depending on the complexity of the transactions.
It’s an enhancement that not only can benefit users using Visualforce pages, but can also benefit a lot of others areas in your application such as triggers and even custom web services.
Visualforce complexity
This one can sometimes be difficult to refactor depending on your application structure and where your page is being used. The more complicated and the more components used in your Visualforce pages also affects how fast your page is rendered by Salesforces’ application servers.
The crooks of this point is that the more Visualforce tags you use the more the application servers have to work in order to render your page and also crucially how long it will tag to load your page.
It isn’t to say you shouldn’t use the built in tags to achieve what you need to get implemented, but perhaps sometimes use pure HTML to avoid additional processing by Salesforce. If it isn’t possible to to do this then another approach is to split your Visualforce page into multiple pages to help reduce page rendering and loading times, whilst also providing the user with a more guided wizard solution.
Call outs
Integration can really have an impact on your page performance and is often one area where you need to be careful about end user perception of the speed of Salesforce. There are two parts to performance regarding integration I’d like to discuss; perceived and actual performance.
If you need to load data from an external system consider non-blocking page loading, meaning let the page load and then make a call out with a loading screen. This really helps the user understand what they are waiting for and reduces end user perception that your application is slow. This is perceived performance. Your page isn’t fully loaded yet, but to the user they can see things loading and have an understanding into what they are waiting for. When we don’t do this and say make a call out as soon as the page loads, it blocks the loading of the page and the user must wait with no visual clues as to why the page isn’t loading. The user may not know that we’re dependent on an external system and will most likely blame the platform being slow.
The point being here is to help guide the user into why and what they are waiting for and to progressively update the page as the data is ready. This really helps with the perceived perception that your page is fast loading.
Actual performance can be improved in several ways, but is dependent sometimes on whether you own or can influence the design of the external web service.
If you have control over the design of your web services you need to connect to, consider these points for performance:
- Make the input and output of the web service as simple as possible.
- Keep the output to the web service as minimal as required. Avoid returning unnecessary data which is never used.
- Consider the communication method carefully, SOAP vs REST.
- Use compression, always.
Governor and executioner limits
Over time I’ve grown to like the governor and executioner limits as they force you to write part optimal code. That said you can still write code which doesn’t breach the limits but doesn’t follow the best practices advised by Saleforce.
Try and avoid the typical issues such as:
- SOQL/SOSL queries inside loops. Load all of the necessary data within one query as this saves a lot of time spent on the database.
- DML inside loops or executing DML for single records. Each time a DML statement is executed a lot of steps need to be done in order to complete the step (triggers, workflow, validation rules etc.). Execute DML with as many records as possible to take advantage of bulk processing.
Conclusion
There are many more ways to help speed up page load times, these are just the starting point and relevant to Salesforce.
Counter to what I’ve mentioned above, don’t also fall into the trap of premature optimisation. It’s better to have a completed page which isn’t running as fast as you’d like but gets what your end users need at this moment. Performance is an ongoing task which needs to be reviewed again and again, be prepared to come back in the future to make more enhancements as your application evolves.
What are your tips and tricks to speeding up Visualforce?
Leave a Reply