[SalesForce] What are Apex Performance Best Practices

Is there a definitive guide somewhere that outlines the best practices for faster executing code?

I am looking for specifics, like

  1. Adding elements to a Set versus to a Map
  2. Testing for null before adding an element to a Set of IDs versus not testing for null, and then using that Set in a query's WHERE clause.
  3. Is it faster to use a trigger with a query to a related object or a workflow field update, where the workflow accesses the related object's fields via the "__r." syntax?

Things like that.

I could test specific scenarios myself, but there are so many, and there are many I am not even thinking about. I was hoping that this is already captured somewhere online.

Thanks.

EDIT: So general consensus seems to be not to micromanage or worry about which data structure would be faster, because performance gains will be minimal, and making the code readable and maintainable is more important. Cool, thanks.

Best Answer

Great question. In opening this can of worms, I would like to noodle the premise if you don't mind :-) just to learn if we're solving performance in the right quadrant. What motivates your question exactly?

easy problem         ^         hard problem
easy solution        |        easy solution
                     |                     
[start here]         |   [graduate to here]
                     |                     
<--------------------+-------------------->
                     |                     
[dragons be here]    |    [data scientists]
                     |                     
easy problem         |         hard problem
hard solution        |        hard solution

Definitely performance is important, but the Force.com platform is pretty good at keeping you within reasonable boundaries. You don't have to worry about nginx vs iis vs apache serving XYZ requests per second. Float above that stuff. Salesforce throws smarts and hardware at those problems so we don't have to.

As a service layer developer, err on the side of inspecting:

  • performance of callouts (web services, third party hooks hanging off your controllers, or crazy stuff living in JavaScript code facing your users via custom buttons, etc)
  • if you're an ISV developing real product, keep swathes of DML out of tests for your patience/sanity's sake, check large inserts and large deletes aren't anywhere near governor limits,
  • check your use of asynchronous tools / set-and-forget methods (like @future, batches, schedules) to detour any heavy lifting away from execution contexts invoked by user interfaces,

Rather than doing legwork for the sake of the Apex runtime, optimize for you the architect, us the developers, them the future maintainers. The Apex runtime will get faster and smarter, you don't need to do it any favours. Principle of least astonishment and semantics wins over tricks every time.

Governor limits are the thoughtful and useful straitjacket that gives us a gentle slap in the face as course correction if code falls outside those reasonable boundaries.

As a client-side developer, invest your valuable time:

  • taking advantage of speedy (JavaScript Remoting) and reactive (Streaming API) features to offer the snappiness (or perceived snappiness) your users expect, decoupled from Apex performance,

  • check the expires attributes of pages holding JavaScript clients, the cache control attributes of static resources (zips of course, concatenated CSS/JS courtesy a non-overkill build script)

  • profile first, shoot later!