apex:actionFunction vs. Visualforce Remoting performance Tuning

Use JavaScript remoting in Visualforce to call methods in Apex controllers from JavaScript. Create pages with complex, dynamic behavior that isn’t possible with the standard Visualforce AJAX components.
JavaScript remoting has three parts:

  • The remote method invocation you add to the Visualforce page, written in JavaScript.
  • The remote method definition in your Apex controller class. This method definition is written in Apex, but there are few differences from normal action methods.
  • The response handler callback function you add to or include in your Visualforce page, written in JavaScript.

Example of using apex:actionFunction:


public with sharing class SearchforContactByName {

    public String customerLastName { get; set; }
    public List searchResults { get; private set; }

    public void searchforCustomerSearch() {
        customerLastName = '%' + customerLastName + '%';
        searchResults = [
            SELECT Id, FirstName, LastName 
            FROM Contact 
            WHERE LastName LIKE :customerLastName 
            ORDER BY LastName, FirstName 
            LIMIT 200
        ];
    }
}
<apex:define name="body">
 <apex:form >  
  <apex:actionFunction name="findCustomerByName" action="{!searchforCustomerSearch}" reRender="customers"
  <apex:param name="customerLastName" assignTo="{!customerLastName}" value=""/>
  </apex:actionFunction>
  <input id="searchField" type="text" placeholder="Enter Last Name"/>
  <button type="button">Search</button>
  <apex:outputPanel layout="block" id="customers">
  <apex:dataTable value="{!searchResults}" var="sr">
  <apex:column >{!sr.LastName}, {!sr.FirstName}</apex:column>
  </apex:dataTable>
  </apex:outputPanel>
 </apex:form>
</apex:define>

Example below show how to use RemoteAction with Sencha Touch example:


Ext.define("ChatterPlus.model.Chatter", {
    extend: "Ext.data.Model",

    config: {
        idProperty: 'Id',

        fields: [
            { name: 'Id', type: 'string', persist: false},
            { name: 'Title', type: 'string'},
            { name: 'Body', type: 'string'},
            { name: 'LikeCount', type: 'string', persist: false},
            { name: 'CommentCount', type: 'string', persist: false},
            { name: 'Comment', type: 'string', persist: false},
            { name: 'Like', type: 'string', persist: false},
            { name: 'ParentId', type: 'string'}
        ],

        validations: [
             { type: 'presence', field: 'Title', message: 'Enter a Title' },
             { type: 'presence', field: 'Body', message: 'Enter a Body' } 
        ],

        //Bind each CRUD functions to a @RemoteAction method in the Apex controller
        proxy: {
            type: 'direct',
            api: {
                read:     ChatterController.Query,
                create:   ChatterController.Add,
                update:   ChatterController.Edit,
                destroy:  ChatterController.Destroy
            },
            limitParam: 'recordCount',   // because "limit" is an Apex keyword
            sortParam: 'sortParams',     // because "sort" is a keyword too
            pageParam: false,            // we don't use this in the controller, so don't send it
            reader: {
                type: 'json',
                rootProperty: 'records',
                messageProperty: 'errorMessage'
            },
            writer: {
                type: 'json',
                root: 'records',
                writeAllFields: false,   // otherwise empty fields will transmit as empty strings, instead of "null"/not present
                allowSingle: false,      // need to always be an array for code simplification
                encode:  false           // docs say "set this to false when using DirectProxy"
            }

        }
    },

});

Remote Controller


    @RemoteAction
    public static Response Add(List chatterData){
        return insertLeadList(chatterData);
    }

    @RemoteAction
    public static Response Destroy(List chatterData){
        return deleteChatterList(chatterData);
    }

    @RemoteAction
    public static Response Edit(List chatterData){
        return editChatterList(chatterData);
    }

    @RemoteAction
    public static Response EditComment(List chatterCommentData){
        return editCommentChatterList(chatterCommentData);
    }

    @RemoteAction
    public static Response Query(QueryRequest qr){

        Response resp = new Response();

        //Enforce a limit on the number of rows requested.
        final integer QUERY_LIMIT = 500;
        if( qr.start >= QUERY_LIMIT ){
            resp.success = false;
            resp.errorMessage = 'Maximum number of records (' + String.valueOf(QUERY_LIMIT) + ') exceeded!';
            return resp;
        }

        try {
            getAllChatter(qr, resp);
        } catch (Exception e) {
            resp.success = false;
            resp.errorMessage = 'Query failed: ' + e.getMessage();
        }

        return resp;
    }

Visualforce View State Performance Tuning

Visualforce pages that contain a form component also contain an encrypted, hidden form field that encapsulates the view state of the page. This view state is automatically created, and as its name suggests, it holds the state of the page – state that includes the components, field values and controller state.

Below is some tips to improve the performance of you Visualforce pages:

Minimize Number of Form tags between apex:page

A Visualforce page manages a single view state, even when the page contains multiple input forms (<apex:form>). Instead of having multiple forms on a page, have a single form and use <apex:actionRegion> to submit portions of the form. The reason is when multiple forms are present in a single page the view state will be retrieved all forms when an action submits. This means the current form may run slower if the other forms have a large view state.

<apex:page controller="UpdateAccountContactController">
  <apex:form>

     <apex:commandButton action="{!saveAccount}" value="Update Account"/>

     <apex:actionRegion>
       <apex:commandButton action="{!saveContacts}" value="Update Contacts"/>
     <!--Contact attributes available for editing -->
    </apex:actionRegion>

  </apex:form>
</apex:page>

Order of Postback Request in Visualforce page:
http://www.salesforce.com/us/developer/docs/pages/Content/pages_controller_postback_request.htm
Check out the execution order of an Visualforce page:
http://www.salesforce.com/us/developer/docs/pages/Content/pages_controller_lifecycle_example.htm

Other things to consider to decrease the size of your view state

  • Use transient keyword
  • http://wp.me/pwk6w-Is

  • Optimize SOQL queries and use Custom Objects to store large quantity data
  • Implement Visualforce Remoting
  • Use Streaming API