My laptop is 300 times faster

In Relative performance of CRUD, while the delete/insert time dominated, the calculation part took more time than I expected too. I had been thinking that it was the governor limits that stopped you from using up too many CPU cycles and that up to those limits you would get pretty high performance, but that did not appear to be the case.

To separate out the CPU part, I created the very basic benchmark below in both Java and Apex. I ran the Java on my 2 year-old laptop (14ms on average) and the Apex on Na7 (5064ms on average). Hence the conclusion that my laptop is 300 times faster. Now I just have to figure out how to get my laptop to scale to a million or so users…

But the lesson also is to be realistic about the performance of any CPU cycle intensive logic in your application. Even for your first user, it is going to be slower than you probably expected.

Java benchmark:

public class Calc {

    public static void main(String[] args) {

        long t1 = System.currentTimeMillis();
        Integer result = calc(200);
        long t2 = System.currentTimeMillis();

        System.out.println("result=" + result);
        System.out.println("ms=" + (t2 - t1));
    }

    private static Integer calc(Integer n) {
        Integer sum = 0;
        for (Integer i = 0; i < n; i++) {
            for (Integer j = 0; j < n; j++) {
                sum += i * j;
            }
        }
        return sum;
    }
}

Apex benchmark:

@isTest
private class CalcTest {

    @isTest
    static void test() {
        System.debug(LoggingLevel.ERROR);

        Long t1 = Datetime.now().getTime();
        Integer result = calc(200);
        Long t2 = Datetime.now().getTime();

        System.debug(LoggingLevel.ERROR, 'result=' + result);
        System.debug(LoggingLevel.ERROR, 'ms=' + (t2 - t1));
    }

    private static Integer calc(Integer n) {
        Integer sum = 0;
        for (Integer i = 0; i < n; i++) {
            for (Integer j = 0; j < n; j++) {
                sum += i * j;
            }
        }
        return sum;
    }
}
Advertisements

Relative performance of CRUD

In an application I have some Apex code that does quite a lot of computation and saves the results in several objects. If the results have been generated before, the code first deletes the existing objects. On adding some timing code, I was surprised at the distribution of the times, particularly how expensive the deletes are and how cheap the reads (selects) are.

Here is the data (values in milliseconds and dealing with a few dozen objects in each case) for a couple of variations:

The parts are:

  • Find: doing a SOQL select to identify the “ids” of the objects to delete
  • Delete: a single Apex “delete ids” call
  • Calculate: Apex “new” calls and various calculations to populate the objects
  • Insert: a single Apex  “insert newIds” call to insert the calculated objects

Static variables are not static for very long

I have been fighting the “10 describe calls” per request governor limit in some code that clones an object graph that includes more than 10 custom types. In one (dead-end) approach I was trying to cache some of the describe information in a static variable referencing a collection. This revealed the surprising (to a Java developer at least) fact that static variables only have request scope and so are no use for trying to build session or application scope caches:

Static variables are only static within the scope of the request. They are not static across the server, or across the entire organization.

From Static and Instance.

Using composition in custom controllers

Custom controllers quickly lose cohesion as data to display is mixed with actions. And custom controllers for wizards (see e.g. Creating a Wizard) are truly ugly as the data and actions for the sequence of pages are added to the single controller class. Also I recently had to implement a wizard that had some pages in common with an existing wizard so that re-use became an issue.

My conclusion is that using more classes is the way to go. This is particularly true for wizards, where the logic is best broken up per page, but also applies to controllers for single pages where the logic might be broken up per page section. Using more classes also benefits the design of the corresponding unit tests.

Here is a contrived example of the wizard case:

public class AbcWizardController {

    public PageOneController pageOne { get; set; }
    public PageTwoController pageTwo { get; set; }

    public AbcWizardController() {
        pageOne = new PageOneController();
        pageTwo = new PageTwoController();
    }
    ...
}

public class PageOneController() {

    public String title {
        get {
            return 'Page One';
        }
    }

    public List<CustomType__c> rows {
        ...
    }

    ...
}

// PageOne.page
<apex:page controller="AbcWizardController">
    <apex:pageBlock>
        <apex:pageBlockSection title="{!pageOne.title}">
            <apex:pageBlockTable value="{!pageOne.rows}" var="row">
                <apex:column value="{!row.Name}"/>
                <apex:column value="{!row.CustomField1__c}"/>
                <apex:column value="{!row.CustomField2__c}"/>
            </apex:pageBlockTable>
        </apex:pageBlockSection>
    </apex:pageBlock>
</apex:page>

A further benefit is that parameter passing to Visualforce components becomes cleaner too. Suppose you have a Visualforce page that presents groups of information that have the same structure and so want to create a Visualforce component for how that information is presented. The parameter passing to that component becomes simple if there is also a corresponding class (SectionController here) nested in the main controller class (XyzController here):

<apex:page controller="XyzController">
    <apex:pageBlock>
        <c:CustomSection section="{!sectionOne}"/>
        <c:CustomSection section="{!sectionTwo}"/>
    </apex:pageBlock>
</apex:page>

// Section.component
<apex:component>

    <apex:attribute name="section" type="SectionController" required="true" description=""/>

    <apex:pageBlockSection title="{!section.title}">
        <apex:pageBlockTable value="{!section.rows}" var="row">
            <apex:column value="{!row.Name}"/>
            <apex:column value="{!row.CustomField1__c}"/>
            <apex:column value="{!row.CustomField2__c}"/>
        </apex:pageBlockTable>
    </apex:pageBlockSection>
</apex:component>

Should the nested classes be made inner classes of the main controller class? There is little benefit to doing that as inner classes can’t see the members of their containing class. So to keep the re-use option open I suggest making the nested classes separate top-level classes. If the nested classes need access to the main controller class remove the direct coupling by using an interface:

public class XyzController implements PqrInterface {

    public SectionController sectionOne { get; set; }
    public SectionController sectionTwo { get; set; }

    public XyzController() {
        sectionOne = new SectionController(this);
        sectionOne = new SectionController(this);
    }
    ...
}

public class SectionController {

    private PqrInterface pqr;

    public SectionController(PqrInterface pqr) {
        this.pqr = pqr;
    }

    ...
}

More on sorting a custom table

This post describes a mild re-working of http://wiki.developerforce.com/index.php/Sorting_Tables; the real solution here is platform support so please vote as described in that article.

(PS See my comment below about using the jQuery tablesorter plugin – probably a better way to go than this server-side solution.)

The reason to make changes is that I wanted to show the current sort direction using the same arrows that the default UI uses and provide a tooltip to let the user know what direction they will get when they click a header. This in turn required more properties to be exposed per column in the Visualforce. And so to control the complexity of that (and avoid hard to find bugs and simplify future refactoring) some changes were needed.

Here is an extract from the finished custom page. All these extracts just show one table column and … for other markup or code that has been taken out. The key point here is the simplicity of the c:SortableLink line.

<style type="text/css">
/* These standard classes tweaked to position the up and down arrow images correctly */
body .pbBody .sortAsc {
    padding-right: 12px;
    background-position-x: right;
    background-position-y: 4px;
}
body .pbBody .sortDesc {
    padding-right: 12px;
    background-position-x: right;
    background-position-y: -8px;
}
<style>
...
<apex:pageBlockTable value="{!payments}" var="row"  id="paymentsTable">
    ...
    <apex:column value="{!row.Status__c}">
        <apex:facet name="header">
            <c:SortableLink sortable="{!statusSortable}" rerender="paymentsTable"/>
        </apex:facet>
    </apex:column>
    ...
</apex:pageBlockTable>

Most of the markup has been moved into this component:

// SortableLink.component
<apex:component >

    <apex:attribute name="sortable" Type="Sortable" required="true" description=""/>
    <apex:attribute name="rerender" Type="Id" required="true" description=""/>

    <apex:commandLink value="{!sortable.label}"
            action="{!sortable.sort}"
            styleClass="{!sortable.styleClass}"
            title="{!sortable.tooltip}"
            rerender="{!rerender}"
            onclick="this.disabled=true; this.innerHTML='Sorting...';"
            />
</apex:component>

That component is relying on the necessary information being held by an instance of this simple class for each column in the controller:

/**
 * Provide sort-related data for a particular field to simplify the creation of a sort direction
 * table header link in a custom sortable table.
 *
 * Delegates to the underlying controller to get the work done.
 */
public class Sortable {

    /**
     * Underlying controller should implement this.
     */
    public interface Sorter {
        PageReference sort(String fieldName);
        Boolean isAscending(String fieldName);
        Boolean isDescending(String fieldName);
        String getLabel(String fieldName);
    }
    
    private String fieldName;
    private Sorter sorter;

    public Sortable(String fieldName, Sorter sorter) {
        this.fieldName = fieldName;
        this.sorter = sorter;
    }
    
    public String label {
        get {
            return sorter.getLabel(fieldName);
        }
    }
    
    public String tooltip {
        get {
           if (sorter.isAscending(fieldName)) {
               return 'Ascending; click for descending';
           } else if (sorter.isDescending(fieldName)) {
               return 'Descending; click for ascending';
           } else {
               return 'Click for ascending';
           }
        }
    }

    public String styleClass {
        get {
           if (sorter.isAscending(fieldName)) {
               return 'sortAsc';
           } else if (sorter.isDescending(fieldName)) {
               return 'sortDesc';
           } else {
               return '';
           }
        }
    }
    
    public PageReference sort() {
        return sorter.sort(fieldName);
    }
}

So the controller has to have a property (unless I’ve missed something in the Visualforce expression language and you can pass parameters to methods) that is an instance of that class per column and also implement the Sortable.Sorter interface:

public class PaymentController implements Sortable.Sorter {

    // Cached as subject to governor limits
    private static Map FIELDS = Schema.SObjectType.Payment__c.fields.getMap();

    // Meta data to simplify the markup in the page for sorting
    ...
    public Sortable statusSortable { get; set; }
    ...

    public PaymentCalculationController(ApexPages.StandardController controller) {
        ...
        statusSortable = new Sortable('Status__c', this);
        ...
    }
    
    private String paymentsAscField;
    private String paymentsDescField;
    
    public PageReference sort(String fieldName) {
        if (fieldName == paymentsAscField) {
            paymentsAscField = null;
            paymentsDescField = fieldName;
        } else {
            paymentsDescField = null;
            paymentsAscField = fieldName;
        }
        applyCurrentSort();
        return null;
    }
    
    public Boolean isAscending(String fieldName) {
        return fieldName == paymentsAscField;
    }
    
    public Boolean isDescending(String fieldName) {
        return fieldName == paymentsDescField;
    }
    
    public String getLabel(String fieldName) {
        Schema.DescribeFieldResult f = FIELDS.get(fieldName).getDescribe();
        return f.label;
    }

    private void applyCurrentSort() {
        Boolean ascending;
        String fieldName;
        if (paymentsAscField != null) {
            ascending = true;
            fieldName = paymentsAscField;
        } else if (paymentsDescField  != null) {
            ascending = false;
            fieldName = paymentsDescField;
        } else {
            // Default to this
            ascending = true;
            fieldName = 'PayeeName__c';
            paymentsAscField  = fieldName;
        }
        payments = (List) SortUtil.sort(payments, fieldName, ascending, null);
    }

    // Collection shown in table
    public List payments {
        get {
            if (payments == null) {
                payments = [select ...];
                applyCurrentSort();
            }
            return payments;
        }
        set;
    }

    ...
}

I ended up using a simplified version of “SuperSort” to do the work:

/**
 * Refactored from http://wiki.developerforce.com/index.php/Sorting_Tables.
 */
public class SortUtil {

    /**
     * This provides in-memory sorting for cases where it isn't appropriate to re-execute a query
     * with a changed "order by".
     *
     * The fieldValueMapping argument allows e.g. a reference id to be translated to the natural
     * value (e.g. the object name) for use in the sort.
     *
     * The returned list can be downcast to the same SObject type as the argument list.
     */
    public static List sort(
            List items,
            String fieldName,
            Boolean ascending,
            Map fieldValueMapping
            ) {
    
        // Field value to the List of SObjects that have that field value
        Map<Object, List> m = new Map<Object, List>();
        for(SObject item : items){
            Object fieldValue = item.get(fieldName);
            if (fieldValueMapping != null && fieldValueMapping.containsKey(fieldValue)) {
                fieldValue = fieldValueMapping.get(fieldValue);
            }
            List l = m.get(fieldValue);
            if (l == null) {
                l = new List();
                m.put(fieldValue, l); 
            }
            l.add(item);
        }
        
        // Sort the field values
        List fieldValues = new List(m.keySet());
        fieldValues.sort();
        
        // Doing this to end up with a list of the right type that can be downcast
        List results = items.clone();
        results.clear();
        
        // Order the SObjects
        if (ascending) {
            for (Integer i = 0; i < fieldValues.size(); i++) {
                Object fieldValue = fieldValues.get(i);
                List<SObject> l = m.get(fieldValue);
                for (Integer j = 0; j < l.size(); j++) {
                    results.add(l.get(j));
                }
            }
        } else {
            for (Integer i = fieldValues.size() - 1; i >= 0; i--) {
                Object fieldValue = fieldValues.get(i);
                List<SObject> l = m.get(fieldValue);
                // If there is some natural ordering here reverse that too
                for (Integer j = l.size() - 1; j >= 0; j--) {
                    results.add(l.get(j));
                }
            }
        }

        return results;
    }
}

All in all an awful lot of work to achieve something that the platform could do way better.

A c:OutputCheckbox for custom pages

While the is an apex:inputCheckbox there is not an apex:outputCheckbox. So its not obvious how to achieve this appearance for a checkbox field in a table in a custom page:

One way to do it is to define 3 components as below and use the c:OutputCheckbox one in the table passing in the boolean value:

// OutputCheckbox.component
<apex:component>
    <apex:attribute name="value" type="Boolean" required="true" description=""/>
    <c:CheckedImage rendered="{!value}"/>
    <c:UncheckedImage rendered="{!(!value)}"/>
</apex:component>

// CheckedImage.component
<apex:component>
    <img src="/img/checkbox_checked.gif" alt="Checked" width="21" height="16" class="checkImg" title="Checked"/>
</apex:component>

// UncheckedImage.component
<apex:component>
    <img src="/img/checkbox_unchecked.gif" alt="Not Checked" width="21" height="16" class="checkImg" title="Not Checked"/>
</apex:component>

The image paths are taken from the corresponding elements in the default UI.