I have a quite complex Visualforce component (edit grid) that is running to slow (2-4 seconds to display) When I say complex I mean:

  • The Component itself is calling other components
  • Many thousand lines of code
  • Using StandardSetController to work and display arbitrary record numbers
  • Reading and writing records and Custom Settings
  • Lot of Schema querying

I am not a newbie so I incorporated all know best practices regarding performant Apex and VF code. As this still results in a poor performance I tried to do some profiling (log file analysis to find out what takes to long and why. But none of the tools I tried really allowed this:

  1. Developer console

    • Terrible slow interface in FF and Chrome
    • Timeline view and Performance Tree to coarse
  2. External Logging with http://loggly.com/

    • As this requires callouts and future methods can't be used in a Visualforce get/set and constructors. But those are critical.
  3. Adding and analysing my own System.debug()

    • As the regular log is already quite big, Salesforce.com seems to strip out all my custom DEBUG lines.

SOS! What other alternatives are there? What do you / did you do in such cases?!

  • 2
    Great question! One of the aspects that can really slow VF down is Viewstate. Particully if you are using lots of VF components in tables, not only can your own view state grow, but also what is known as 'internal viewstate'. Have you enabled the Viewstate option on your User (requires Developer Mode) to inspect the size of your viewstate? You will then find a Viewstate tab appears at the bottom of the page once your page has finished loading. Dec 17 '12 at 15:10
  • 1
    At my org we have an extra custom object to log execution times of our methods. We defining a start and end points (eg. before and after complex function) so the time can be calculated. Additionally i'm tracking degug outputs at the "Debug Logs" page where usually debugs are not truncated. The developer console could be adapted, that is you can set the logging level for that. I'm using raw log only - it is much faster. Dec 17 '12 at 15:20
  • Regarding 'internal viewstate', take a look at this, salesforce.stackexchange.com/questions/4537/…. Not sure how complex your page is, bottom line is, your sadly not the only one consuming viewstate. Dec 17 '12 at 15:51
  • Thanks Andrew for sharing this. I will check it out right now. I just found out that my component is using up 55 KB of ViewState and 45 KB are Internal. So nothing I can do about it?! Dec 17 '12 at 15:54
  • Yes and no, there is a link with the complexity of your page, take a look at the answer for the other question I linked to. Also keep in mind that even if its VF output components, they still carry an overhead. So if you can use regular HTML tags for output use those. Dec 17 '12 at 16:27

Other Tools. Your tools list is a good one, as is your question! In addition I would recommend you take a look at the Viewstate contents via the 'Show Viewstate in Developer Mode' setting on your user. This enables the following view on your page. Note that you can use 'transient' to control this for information you define in your controller that is essentially request scope only (not needed to be retained next time round). The research done here also proves that overuse of VF components, especially in large list rendering scenarios can cause the 'internal' view state to grow, so watch out for this as well.

enter image description here

Best Practice for Performance in VF

  • Monitor the size of your view state. Use the transient modifier where you can. Large Viewstates take a long time to serialise and deserialise and are known to impact page load, save and VF AJAX interactions (not JavaScript Remoting see below) under large volumes (see below for particular sensitive scenarios).
  • Using VF components in large tables/repeats, each VF component e.g. apex:inputField carries quite a lot of internal view state baggage and to some degree HTML output. So keep an eye on this and use pagination where you can / users tolerate.
  • Try to control the scope of your rerender attributes if you are using VF AJAX features such as apex:actionSupport and apex:actionFunction.
  • Consider using JavaScript Remoting, this is a shift in development style, as you loose automatic management of your pages state. Effectively pushing the state in the browser. However the speed benifits are significant. Though you do need of course more JavaScript skills.
  • Mix and Match. You can btw, mix the use of traditional VF Components / Bindings / AJAX (as per above) and JavaScript Remoting. So this maybe an option for events that your performing currently that don't actually update the state more refresh or default things on your page. Or for example use only VF viewstate for load and save of the page and for all tab out/AJAX stuff utilise Java Script Remoting. Of course while this will help with interaction once the page loads, it won't help address page load times necessarily, though may if in implementing it, it helps reduce your viewstate. Mix and Match approach is really only helpfully if your migrating and/or have limited coding time, I would not recommend it as a best practice from scratch necessarily.
  • Andrew: From reading you other research post, I just commented out checkboxes, converted apex:inputXXX to outputXXX but did not see a significant decrease in ViewState. Before I proceed switching Actions to AJAX I will try to strip down the markup. Dec 17 '12 at 16:12
  • Oddly even the standard VF output components also consume internal view state. If you don't need the formatting capabilities (or can do it in Apex) just output via raw HTML tags to be sure. What is your viewstate size btw, have you got much from the View State debugger i mentioned above? Dec 17 '12 at 16:14

The short answer is...debugging is very hard in this sort of situation. The methods that you mentioned are all valid but won't yield the best results.

I like the idea of trying to monitor and skinny down the view state. Andrew's comment about enabling the viewstate option is how you would monitor. Try using the transient keyword on variables that don't need to be serialized between requests to "skinny" things down. If you are displaying lists, try using the StandardSetController to implement paging.

The serialization/deserialization of the viewstate is almost always the culprit for slow VF performance. Get this smaller and you'll likely see big performance gains.

  • Thanks Kevin! I'm already using StandardSetController and changing variables to transient always produces errors. Is it true, that transient won't live after an action call or a rerender?! Dec 17 '12 at 15:49
  • I don't believe so because the controller is actually re-initialized on one of those calls so the values of those variables would be lost too. Are they something that you can re-query when a a re-render is called? Dec 17 '12 at 17:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.